introduced ChipOverview
route and component, refactored Home
to use DreamCardCompact
for streamlined rendering, and extracted DailyHighlights
into a reusable component
Signed-off-by: Matthias Puchstein <matthias@puchstein.bayern>
This commit is contained in:
@@ -10,6 +10,7 @@ import DreamPage from "./pages/DreamPage.tsx";
|
|||||||
import ProfilePage from "./pages/ProfilePage.tsx";
|
import ProfilePage from "./pages/ProfilePage.tsx";
|
||||||
import Home from "./pages/Home.tsx";
|
import Home from "./pages/Home.tsx";
|
||||||
import Overview from "./pages/Overview.tsx";
|
import Overview from "./pages/Overview.tsx";
|
||||||
|
import ChipOverview from "./pages/ChipOverview.tsx";
|
||||||
|
|
||||||
function Archive() {
|
function Archive() {
|
||||||
return (
|
return (
|
||||||
@@ -117,7 +118,7 @@ function AppContent() {
|
|||||||
<Route path="/" element={<Overview/>}/>
|
<Route path="/" element={<Overview/>}/>
|
||||||
<Route path="/home" element={<Home/>}/>
|
<Route path="/home" element={<Home/>}/>
|
||||||
<Route path="/feed" element={<Feed/>}/>
|
<Route path="/feed" element={<Feed/>}/>
|
||||||
<Route path="/chip" element={<></>}/>
|
<Route path="/chip" element={<ChipOverview/>}/>
|
||||||
<Route path="/archive" element={<Archive/>}/>
|
<Route path="/archive" element={<Archive/>}/>
|
||||||
<Route path="/profile" element={<ProfilePage/>}/>
|
<Route path="/profile" element={<ProfilePage/>}/>
|
||||||
<Route path="/dream/:id" element={<DreamPage/>}/>
|
<Route path="/dream/:id" element={<DreamPage/>}/>
|
||||||
|
99
src/components/DailyHighlights.tsx
Normal file
99
src/components/DailyHighlights.tsx
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import {primaryMoodCategories, topDreamTopics} from '../data/MockDailyHighlights';
|
||||||
|
import {getCardStyle, getTextStyle} from '../styles/StyleUtils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HighlightCard component displays a single highlight item with a colored progress bar
|
||||||
|
*/
|
||||||
|
interface HighlightItemProps {
|
||||||
|
label: string;
|
||||||
|
percentage: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HighlightCard = ({label, percentage}: HighlightItemProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="mb-3 rounded-lg overflow-hidden shadow-md hover:shadow-lg transition-all duration-300 hover:transform hover:scale-[1.02] hover:translate-y-[-2px] animate-fadeIn floating">
|
||||||
|
<div className="relative p-3 backdrop-blur-sm"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.25), rgba(213, 0, 249, 0.25))',
|
||||||
|
boxShadow: 'inset 0 0 15px rgba(166, 77, 255, 0.2)'
|
||||||
|
}}>
|
||||||
|
<div className="flex justify-between items-center mb-1">
|
||||||
|
<span className="font-medium" style={{color: 'var(--accent)'}}>{label}</span>
|
||||||
|
<span className="text-sm" style={getTextStyle()}>{percentage}%</span>
|
||||||
|
</div>
|
||||||
|
<div className="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden"
|
||||||
|
style={{boxShadow: '0 2px 5px var(--shadow)'}}>
|
||||||
|
<div
|
||||||
|
className="h-full rounded-full"
|
||||||
|
style={{
|
||||||
|
width: `${percentage}%`,
|
||||||
|
background: 'var(--accent-gradient)',
|
||||||
|
boxShadow: 'inset 0 0 10px rgba(166, 77, 255, 0.5)'
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div className="absolute inset-0 rounded-lg pointer-events-none"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.05), rgba(213, 0, 249, 0.05))',
|
||||||
|
border: '1px solid rgba(166, 77, 255, 0.1)',
|
||||||
|
zIndex: 1
|
||||||
|
}}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DailyHighlights component displays the daily highlights section
|
||||||
|
* including top dream topics and mood categories
|
||||||
|
*/
|
||||||
|
export const DailyHighlights = () => {
|
||||||
|
return (
|
||||||
|
<div className={getCardStyle().className}
|
||||||
|
style={getCardStyle()}>
|
||||||
|
<h3 className="font-bold mb-3 dream-title">Tägliche Highlights</h3>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div
|
||||||
|
className="p-4 rounded-lg backdrop-blur-sm transition-all duration-300 hover:transform hover:scale-[1.01]"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.15), rgba(213, 0, 249, 0.15))',
|
||||||
|
boxShadow: '0 8px 20px var(--shadow), inset 0 0 10px rgba(166, 77, 255, 0.1)',
|
||||||
|
border: '1px solid rgba(166, 77, 255, 0.1)'
|
||||||
|
}}>
|
||||||
|
<h4 className="font-medium mb-3 dream-title text-base">Top Traumthemen</h4>
|
||||||
|
<div className="mb-2">
|
||||||
|
{topDreamTopics.map((topic, index) => (
|
||||||
|
<HighlightCard
|
||||||
|
key={index}
|
||||||
|
label={topic.label}
|
||||||
|
percentage={topic.percentage}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="p-4 rounded-lg backdrop-blur-sm transition-all duration-300 hover:transform hover:scale-[1.01]"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.15), rgba(213, 0, 249, 0.15))',
|
||||||
|
boxShadow: '0 8px 20px var(--shadow), inset 0 0 10px rgba(166, 77, 255, 0.1)',
|
||||||
|
border: '1px solid rgba(166, 77, 255, 0.1)'
|
||||||
|
}}>
|
||||||
|
<h4 className="font-medium mb-3 dream-title text-base">Stimmungskategorien</h4>
|
||||||
|
<div className="mb-2">
|
||||||
|
{primaryMoodCategories.map((mood, index) => (
|
||||||
|
<HighlightCard
|
||||||
|
key={index}
|
||||||
|
label={mood.label}
|
||||||
|
percentage={mood.percentage}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
57
src/components/DreamCardCompact.tsx
Normal file
57
src/components/DreamCardCompact.tsx
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import {NavLink} from 'react-router-dom';
|
||||||
|
import {formatDateSimple} from '../utils/DateUtils';
|
||||||
|
import Dream from '../types/Dream';
|
||||||
|
import User from '../types/User';
|
||||||
|
|
||||||
|
interface DreamCardCompactProps {
|
||||||
|
dream: Dream;
|
||||||
|
index: number;
|
||||||
|
showUser?: boolean;
|
||||||
|
user?: User;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DreamCardCompact = ({dream, index, showUser = false, user}: DreamCardCompactProps) => {
|
||||||
|
return (
|
||||||
|
<NavLink to={`/dream/${dream.id}`}
|
||||||
|
className="block transition-all duration-300 hover:transform hover:scale-[1.02] hover:translate-y-[-2px] animate-fadeIn rounded-lg mb-4 floating">
|
||||||
|
<div
|
||||||
|
className="py-1.5 px-2 backdrop-blur-sm"
|
||||||
|
style={{
|
||||||
|
animationDelay: `${index * 0.1}s`,
|
||||||
|
background: 'linear-gradient(135deg, rgba(166, 77, 255, 0.15), rgba(213, 0, 249, 0.15))',
|
||||||
|
boxShadow: '0 8px 20px var(--shadow), inset 0 0 10px rgba(166, 77, 255, 0.1)',
|
||||||
|
border: '1px solid rgba(166, 77, 255, 0.1)',
|
||||||
|
borderRadius: '0.5rem'
|
||||||
|
}}>
|
||||||
|
<div className="flex items-center justify-between mb-1">
|
||||||
|
{showUser && user && (
|
||||||
|
<div className="pl-2" style={{width: '90px', minWidth: '90px'}}>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<div
|
||||||
|
className="w-6 h-6 rounded-full mr-1.5 flex items-center justify-center overflow-hidden bg-[var(--accent-soft)] border border-[var(--accent)]">
|
||||||
|
{user.profilePicture ? (
|
||||||
|
<img src={`/assets/profiles/${user.profilePicture}`}
|
||||||
|
alt={user.name} className="w-full h-full object-cover"/>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
className="text-xs text-[var(--text)]">{user.name.charAt(0)}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className="font-medium text-xs text-[var(--text)]">{user.name}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex-1 text-center">
|
||||||
|
<h4 className="font-medium text-[var(--accent)] text-xs leading-tight">{dream.title}</h4>
|
||||||
|
<p className="text-xs text-[var(--text-muted)] mt-0.5">
|
||||||
|
{formatDateSimple(dream.date)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/* Add an empty div to balance the layout when user is shown */}
|
||||||
|
{showUser && user && <div className="invisible" style={{width: '90px', minWidth: '90px'}}></div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NavLink>
|
||||||
|
);
|
||||||
|
};
|
3
src/pages/ChipOverview.tsx
Normal file
3
src/pages/ChipOverview.tsx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export default function ChipOverview() {
|
||||||
|
return <></>
|
||||||
|
}
|
@@ -1,11 +1,12 @@
|
|||||||
import {mockDreams} from '../data/MockDreams';
|
import {mockDreams} from '../data/MockDreams';
|
||||||
import {MockUserMap} from '../data/MockUsers';
|
import {MockUserMap} from '../data/MockUsers';
|
||||||
import {getSortedDreamsByDate} from '../utils/DreamUtils.ts';
|
import {getSortedDreamsByDate} from '../utils/DreamUtils.ts';
|
||||||
import {primaryMoodCategories, topDreamTopics} from '../data/MockDailyHighlights';
|
|
||||||
import {getBackgroundStyle, getCardStyle, getTextStyle} from '../styles/StyleUtils';
|
import {getBackgroundStyle, getCardStyle, getTextStyle} from '../styles/StyleUtils';
|
||||||
import {formatDateFull, formatDateSimple} from '../utils/DateUtils';
|
import {formatDateFull} from '../utils/DateUtils';
|
||||||
import {NavLink} from 'react-router-dom';
|
import {NavLink} from 'react-router-dom';
|
||||||
import {DreamRecord} from "../components/DreamRecord.tsx";
|
import {DreamRecord} from "../components/DreamRecord.tsx";
|
||||||
|
import {DreamCardCompact} from "../components/DreamCardCompact.tsx";
|
||||||
|
import {DailyHighlights} from "../components/DailyHighlights.tsx";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const currentUser = MockUserMap.get(4); // Neo Quantum
|
const currentUser = MockUserMap.get(4); // Neo Quantum
|
||||||
@@ -62,17 +63,11 @@ export default function Home() {
|
|||||||
{personalDreams.length > 0 ? (
|
{personalDreams.length > 0 ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{personalDreams.map((dream, index) => (
|
{personalDreams.map((dream, index) => (
|
||||||
<NavLink key={dream.id} to={`/dream/${dream.id}`}
|
<DreamCardCompact
|
||||||
className="block transition-all duration-300 hover:transform hover:scale-[1.02] hover:translate-y-[-2px] bg-[var(--bg)] shadow-md backdrop-blur-sm animate-fadeIn rounded-lg mb-2">
|
key={dream.id}
|
||||||
<div
|
dream={dream}
|
||||||
className="p-2"
|
index={index}
|
||||||
style={{animationDelay: `${index * 0.1}s`}}>
|
/>
|
||||||
<h4 className="font-medium text-[var(--accent)] text-sm">{dream.title}</h4>
|
|
||||||
<p className="text-xs text-[var(--text-muted)]">
|
|
||||||
{formatDateSimple(dream.date)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</NavLink>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -92,77 +87,23 @@ export default function Home() {
|
|||||||
{friendsDreams.map((dream, index) => {
|
{friendsDreams.map((dream, index) => {
|
||||||
const dreamUser = MockUserMap.get(dream.userId);
|
const dreamUser = MockUserMap.get(dream.userId);
|
||||||
return (
|
return (
|
||||||
<NavLink key={dream.id} to={`/dream/${dream.id}`}
|
<DreamCardCompact
|
||||||
className="block transition-all duration-300 hover:transform hover:scale-[1.02] hover:translate-y-[-2px] bg-[var(--bg)] shadow-md backdrop-blur-sm animate-fadeIn rounded-lg mb-2">
|
key={dream.id}
|
||||||
<div
|
dream={dream}
|
||||||
className="p-2"
|
index={index}
|
||||||
style={{animationDelay: `${index * 0.1}s`}}>
|
showUser={true}
|
||||||
<div className="flex items-center mb-1">
|
user={dreamUser}
|
||||||
<div
|
/>
|
||||||
className="w-5 h-5 rounded-full mr-1 flex items-center justify-center overflow-hidden bg-[var(--accent-soft)] border border-[var(--accent)]">
|
|
||||||
{dreamUser?.profilePicture ? (
|
|
||||||
<img src={`/assets/profiles/${dreamUser.profilePicture}`}
|
|
||||||
alt={dreamUser.name} className="w-full h-full object-cover"/>
|
|
||||||
) : (
|
|
||||||
<span
|
|
||||||
className="text-xs text-[var(--text)]">{dreamUser?.name.charAt(0)}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
className="font-medium text-xs text-[var(--text)]">{dreamUser?.name}</span>
|
|
||||||
</div>
|
|
||||||
<h4 className="font-medium text-[var(--accent)] text-sm">{dream.title}</h4>
|
|
||||||
<p className="text-xs text-[var(--text-muted)]">
|
|
||||||
{formatDateSimple(dream.date)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</NavLink>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
{/* Daily Highlights */
|
{/* Daily Highlights */}
|
||||||
}
|
<NavLink to='/archive'>
|
||||||
<div className={getCardStyle().className}
|
<DailyHighlights/>
|
||||||
style={getCardStyle()}>
|
</NavLink>
|
||||||
<h3 className="font-bold mb-3 dream-title">Tägliche Highlights</h3>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div className="p-3 rounded-lg"
|
|
||||||
style={getBackgroundStyle('card')}>
|
|
||||||
<h4 className="font-medium mb-2" style={getTextStyle('accent')}>Top
|
|
||||||
Traumthemen</h4>
|
|
||||||
<ul className="list-disc pl-5 mb-4">
|
|
||||||
{topDreamTopics.map((topic, index) => (
|
|
||||||
<li key={index}
|
|
||||||
className="text-sm mb-1 transition-all duration-300 hover:transform hover:translate-x-1"
|
|
||||||
style={getTextStyle()}>
|
|
||||||
<span
|
|
||||||
style={{color: 'var(--accent-soft)'}}>{topic.label}:</span> {topic.percentage}%
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="p-3 rounded-lg"
|
|
||||||
style={getBackgroundStyle('card')}>
|
|
||||||
<h4 className="font-medium mb-2"
|
|
||||||
style={getTextStyle('accent')}>Stimmungskategorien</h4>
|
|
||||||
<ul className="list-disc pl-5">
|
|
||||||
{primaryMoodCategories.map((mood, index) => (
|
|
||||||
<li key={index}
|
|
||||||
className="text-sm mb-1 transition-all duration-300 hover:transform hover:translate-x-1"
|
|
||||||
style={getTextStyle()}>
|
|
||||||
<span
|
|
||||||
style={{color: 'var(--accent-soft)'}}>{mood.label}:</span> {mood.percentage}%
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Ad Banner */
|
{/* Ad Banner */
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user