added utility functions for date formatting and styling, refactored components to use reusable helpers
Signed-off-by: Matthias Puchstein <matthias@puchstein.bayern>
This commit is contained in:
@@ -4,6 +4,7 @@ import Navbar from './components/Navbar';
|
|||||||
import TopBar from './components/TopBar';
|
import TopBar from './components/TopBar';
|
||||||
import SplashScreen from './components/SplashScreen';
|
import SplashScreen from './components/SplashScreen';
|
||||||
import {BrowserRouter, Route, Routes, useLocation} from 'react-router-dom';
|
import {BrowserRouter, Route, Routes, useLocation} from 'react-router-dom';
|
||||||
|
import {formatDateSimple} from './utils/DateUtils';
|
||||||
import Feed from "./pages/Feed.tsx";
|
import Feed from "./pages/Feed.tsx";
|
||||||
import DreamPage from "./pages/DreamPage.tsx";
|
import DreamPage from "./pages/DreamPage.tsx";
|
||||||
import ProfilePage from "./pages/ProfilePage.tsx";
|
import ProfilePage from "./pages/ProfilePage.tsx";
|
||||||
@@ -89,7 +90,7 @@ function Archive() {
|
|||||||
Dream #{item}
|
Dream #{item}
|
||||||
</h3>
|
</h3>
|
||||||
<span style={{ color: 'var(--text-muted)' }}>
|
<span style={{ color: 'var(--text-muted)' }}>
|
||||||
{new Date().toLocaleDateString()}
|
{formatDateSimple(new Date())}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-4">
|
<p className="mb-4">
|
||||||
|
@@ -3,6 +3,8 @@ import Dream from '../types/Dream';
|
|||||||
import type User from "../types/User.ts";
|
import type User from "../types/User.ts";
|
||||||
import {NavLink} from "react-router-dom";
|
import {NavLink} from "react-router-dom";
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
|
import {getAccentStyle, getTextStyle} from '../styles/StyleUtils';
|
||||||
|
import {formatDateWithTime} from '../utils/DateUtils';
|
||||||
|
|
||||||
interface DreamCardProps {
|
interface DreamCardProps {
|
||||||
dream: Dream;
|
dream: Dream;
|
||||||
@@ -32,28 +34,26 @@ export default function DreamCard({dream, user, animationDelay = 0}: DreamCardPr
|
|||||||
style={{borderColor: 'var(--accent-soft)'}}
|
style={{borderColor: 'var(--accent-soft)'}}
|
||||||
/>
|
/>
|
||||||
<div className="absolute -bottom-1 -right-1 w-4 h-4 bg-accent rounded-full"
|
<div className="absolute -bottom-1 -right-1 w-4 h-4 bg-accent rounded-full"
|
||||||
style={{backgroundColor: 'var(--accent)'}}></div>
|
style={getAccentStyle()}></div>
|
||||||
</div>
|
</div>
|
||||||
<span className="ml-4 font-semibold text-left">{user?.name} <span className="text-text-muted">hat geträumt:</span></span>
|
<span className="ml-4 font-semibold text-left">{user?.name} <span className="text-text-muted">hat geträumt:</span></span>
|
||||||
</div>
|
</div>
|
||||||
<h2 className="title text-left dreamy-text text-lg">
|
<h2 className="title text-left dreamy-text text-lg">
|
||||||
{dream.title}
|
{dream.title}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-2 line-clamp-2 text-left">
|
<p className="mt-2 line-clamp-2 text-left" style={getTextStyle()}>
|
||||||
{(dream.input.inputType === 'text' && dream.input.input)
|
{(dream.input.inputType === 'text' && dream.input.input)
|
||||||
|| (dream.input.inputType === 'audio' && dream.input.transcript)
|
|| (dream.input.inputType === 'audio' && dream.input.transcript)
|
||||||
|| (dream.input.inputType === 'image' && dream.input.description)}
|
|| (dream.input.inputType === 'image' && dream.input.description)}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex justify-between items-center mt-3">
|
<div className="flex justify-between items-center mt-3">
|
||||||
<p className="timestamp text-left">
|
<p className="timestamp text-left" style={getTextStyle('muted')}>
|
||||||
{dream.date.toLocaleDateString('de-DE', {
|
{formatDateWithTime(dream.date)}
|
||||||
day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit',
|
|
||||||
})}
|
|
||||||
</p>
|
</p>
|
||||||
<div className="flex space-x-2">
|
<div className="flex space-x-2">
|
||||||
{/* Display dream type as a tag */}
|
{/* Display dream type as a tag */}
|
||||||
<span className="px-2 py-1 text-xs rounded-full bg-accent-soft text-text"
|
<span className="px-2 py-1 text-xs rounded-full bg-accent-soft text-text"
|
||||||
style={{backgroundColor: 'var(--accent-soft)', color: 'var(--text)'}}>
|
style={getAccentStyle(true)}>
|
||||||
{dream.input.inputType}
|
{dream.input.inputType}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useState} from 'react';
|
||||||
import logotext from "../assets/logotext.svg";
|
import logotext from "../assets/logotext.svg";
|
||||||
import {NavLink} from "react-router-dom";
|
import {NavLink} from "react-router-dom";
|
||||||
|
import {getBackgroundStyle, getTextStyle} from '../styles/StyleUtils';
|
||||||
|
|
||||||
export default function TopBar() {
|
export default function TopBar() {
|
||||||
const [visible, setVisible] = useState(true);
|
const [visible, setVisible] = useState(true);
|
||||||
@@ -56,9 +57,7 @@ export default function TopBar() {
|
|||||||
|
|
||||||
return (<div
|
return (<div
|
||||||
className={`fixed top-0 left-0 right-0 py-2 md:py-3 px-3 md:px-4 flex items-center transition-transform duration-300 z-20 ${visible ? 'transform-none' : 'transform -translate-y-full'}`}
|
className={`fixed top-0 left-0 right-0 py-2 md:py-3 px-3 md:px-4 flex items-center transition-transform duration-300 z-20 ${visible ? 'transform-none' : 'transform -translate-y-full'}`}
|
||||||
style={{
|
style={getBackgroundStyle('topbar')}
|
||||||
background: 'var(--accent-gradient)', boxShadow: '0 2px 10px var(--shadow)'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between w-full max-w-6xl mx-auto">
|
<div className="flex items-center justify-between w-full max-w-6xl mx-auto">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@@ -74,16 +73,14 @@ export default function TopBar() {
|
|||||||
onClick={toggleTheme}
|
onClick={toggleTheme}
|
||||||
className="p-2 rounded-full focus:outline-none transition-transform hover:scale-110"
|
className="p-2 rounded-full focus:outline-none transition-transform hover:scale-110"
|
||||||
aria-label="Toggle theme"
|
aria-label="Toggle theme"
|
||||||
style={{
|
style={getBackgroundStyle('card')}
|
||||||
backgroundColor: 'var(--card)', boxShadow: '0 2px 8px var(--shadow)'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{darkMode ? (<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 md:h-6 md:w-6" fill="none"
|
{darkMode ? (<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 md:h-6 md:w-6" fill="none"
|
||||||
viewBox="0 0 24 24" stroke="currentColor" style={{color: 'var(--accent)'}}>
|
viewBox="0 0 24 24" stroke="currentColor" style={getTextStyle('accent')}>
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||||
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/>
|
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/>
|
||||||
</svg>) : (<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 md:h-6 md:w-6" fill="none"
|
</svg>) : (<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 md:h-6 md:w-6" fill="none"
|
||||||
viewBox="0 0 24 24" stroke="currentColor" style={{color: 'var(--accent-dark)'}}>
|
viewBox="0 0 24 24" stroke="currentColor" style={getTextStyle('accent')}>
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||||
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/>
|
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/>
|
||||||
</svg>)}
|
</svg>)}
|
||||||
|
@@ -5,6 +5,7 @@ import {mockDreams} from '../data/MockDreams';
|
|||||||
import MockUsers from '../data/MockUsers';
|
import MockUsers from '../data/MockUsers';
|
||||||
import User from '../types/User';
|
import User from '../types/User';
|
||||||
import type Dream from "../types/Dream.ts";
|
import type Dream from "../types/Dream.ts";
|
||||||
|
import {formatDateNumeric, formatDateWithTime} from '../utils/DateUtils';
|
||||||
|
|
||||||
export default function DreamPage() {
|
export default function DreamPage() {
|
||||||
const {id} = useParams<{ id: string }>();
|
const {id} = useParams<{ id: string }>();
|
||||||
@@ -48,13 +49,7 @@ export default function DreamPage() {
|
|||||||
</h1>
|
</h1>
|
||||||
{user && (<p className="mt-1 text-white/80 text-sm sm:text-base">
|
{user && (<p className="mt-1 text-white/80 text-sm sm:text-base">
|
||||||
{user.name} •{' '}
|
{user.name} •{' '}
|
||||||
{dream.date.toLocaleDateString('de-DE', {
|
{formatDateWithTime(dream.date)}
|
||||||
day: '2-digit',
|
|
||||||
month: '2-digit',
|
|
||||||
year: 'numeric',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
})}
|
|
||||||
</p>)}
|
</p>)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -150,9 +145,7 @@ export default function DreamPage() {
|
|||||||
<div className="flex flex-col sm:flex-row sm:justify-between">
|
<div className="flex flex-col sm:flex-row sm:justify-between">
|
||||||
<span className="font-medium mb-1 sm:mb-0">Datum</span>
|
<span className="font-medium mb-1 sm:mb-0">Datum</span>
|
||||||
<span>
|
<span>
|
||||||
{dream.date.toLocaleDateString('de-DE', {
|
{formatDateNumeric(dream.date)}
|
||||||
day: '2-digit', month: '2-digit', year: 'numeric',
|
|
||||||
})}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -3,17 +3,14 @@ import {mockDreams} from '../data/MockDreams';
|
|||||||
import {MockUserMap} from '../data/MockUsers';
|
import {MockUserMap} from '../data/MockUsers';
|
||||||
import {getSortedDreamsByDate} from '../data/DreamUtils';
|
import {getSortedDreamsByDate} from '../data/DreamUtils';
|
||||||
import {primaryMoodCategories, topDreamTopics} from '../data/MockDailyHighlights';
|
import {primaryMoodCategories, topDreamTopics} from '../data/MockDailyHighlights';
|
||||||
|
import {getAccentStyle, getBackgroundStyle, getCardStyle, getTextStyle} from '../styles/StyleUtils';
|
||||||
|
import {formatDateFull, formatDateSimple} from '../utils/DateUtils';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [inputMode, setInputMode] = useState<'text' | 'drawing'>('text');
|
const [inputMode, setInputMode] = useState<'text' | 'drawing'>('text');
|
||||||
const currentUser = MockUserMap.get(4); // Neo Quantum
|
const currentUser = MockUserMap.get(4); // Neo Quantum
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
const formattedDate = currentDate.toLocaleDateString('de-DE', {
|
const formattedDate = formatDateFull(currentDate);
|
||||||
weekday: 'long',
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get personal dreams (latest 3 for user ID 4)
|
// Get personal dreams (latest 3 for user ID 4)
|
||||||
const personalDreams = getSortedDreamsByDate(
|
const personalDreams = getSortedDreamsByDate(
|
||||||
@@ -29,21 +26,17 @@ export default function Home() {
|
|||||||
<div className="p-4 dream-container backdrop-blur-md bg-opacity-30"
|
<div className="p-4 dream-container backdrop-blur-md bg-opacity-30"
|
||||||
style={{backgroundColor: 'transparent', boxShadow: '0 10px 30px var(--shadow)'}}>
|
style={{backgroundColor: 'transparent', boxShadow: '0 10px 30px var(--shadow)'}}>
|
||||||
{/* Welcome Card */}
|
{/* Welcome Card */}
|
||||||
<div className="dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01]"
|
<div className={getCardStyle().className}
|
||||||
style={{backgroundColor: 'var(--card)', color: 'var(--text)'}}>
|
style={getCardStyle()}>
|
||||||
<h1 className="text-2xl font-bold mb-2 dream-title">Hallo Neo!</h1>
|
<h1 className="text-2xl font-bold mb-2 dream-title">Hallo Neo!</h1>
|
||||||
<p className="text-sm" style={{color: 'var(--text-muted)'}}>{formattedDate}</p>
|
<p className="text-sm" style={getTextStyle('muted')}>{formattedDate}</p>
|
||||||
<p className="mt-2" style={{color: 'var(--text)'}}>Willkommen zurück in deiner Traumwelt.</p>
|
<p className="mt-2" style={getTextStyle()}>Willkommen zurück in deiner Traumwelt.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Streak Notification */}
|
{/* Streak Notification */}
|
||||||
<div
|
<div
|
||||||
className="dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01] floating"
|
className={getCardStyle(true).className}
|
||||||
style={{
|
style={getBackgroundStyle('accent-gradient')}>
|
||||||
background: 'var(--accent-gradient)',
|
|
||||||
color: 'white',
|
|
||||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3)'
|
|
||||||
}}>
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-3">
|
<div className="mr-3">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-8 w-8" fill="none" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-8 w-8" fill="none" viewBox="0 0 24 24"
|
||||||
@@ -60,28 +53,22 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Input Card */}
|
{/* Input Card */}
|
||||||
<div className="dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01]"
|
<div className={getCardStyle().className}
|
||||||
style={{backgroundColor: 'var(--card)', color: 'var(--text)'}}>
|
style={getCardStyle()}>
|
||||||
<div className="flex justify-between items-center mb-3">
|
<div className="flex justify-between items-center mb-3">
|
||||||
<h3 className="font-bold dream-title">Neuer Traum</h3>
|
<h3 className="font-bold dream-title">Neuer Traum</h3>
|
||||||
<div className="flex rounded-lg overflow-hidden" style={{border: '1px solid var(--accent-soft)'}}>
|
<div className="flex rounded-lg overflow-hidden" style={{border: '1px solid var(--accent-soft)'}}>
|
||||||
<button
|
<button
|
||||||
className={`px-3 py-1 text-sm transition-all duration-200`}
|
className={`px-3 py-1 text-sm transition-all duration-200`}
|
||||||
onClick={() => setInputMode('text')}
|
onClick={() => setInputMode('text')}
|
||||||
style={{
|
style={getAccentStyle(false, inputMode === 'text')}
|
||||||
backgroundColor: inputMode === 'text' ? 'var(--accent)' : 'transparent',
|
|
||||||
color: inputMode === 'text' ? 'white' : 'var(--text)'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Text
|
Text
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`px-3 py-1 text-sm transition-all duration-200`}
|
className={`px-3 py-1 text-sm transition-all duration-200`}
|
||||||
onClick={() => setInputMode('drawing')}
|
onClick={() => setInputMode('drawing')}
|
||||||
style={{
|
style={getAccentStyle(false, inputMode === 'drawing')}
|
||||||
backgroundColor: inputMode === 'drawing' ? 'var(--accent)' : 'transparent',
|
|
||||||
color: inputMode === 'drawing' ? 'white' : 'var(--text)'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Zeichnung
|
Zeichnung
|
||||||
</button>
|
</button>
|
||||||
@@ -94,8 +81,8 @@ export default function Home() {
|
|||||||
rows={4}
|
rows={4}
|
||||||
placeholder="Beschreibe deinen Traum..."
|
placeholder="Beschreibe deinen Traum..."
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg)',
|
...getBackgroundStyle('normal'),
|
||||||
color: 'var(--text)',
|
...getTextStyle(),
|
||||||
border: '1px solid var(--accent-soft)'
|
border: '1px solid var(--accent-soft)'
|
||||||
}}
|
}}
|
||||||
></textarea>
|
></textarea>
|
||||||
@@ -103,17 +90,17 @@ export default function Home() {
|
|||||||
<div
|
<div
|
||||||
className="w-full h-40 rounded-lg mb-3 flex items-center justify-center border-2 border-dashed transition-all duration-200"
|
className="w-full h-40 rounded-lg mb-3 flex items-center justify-center border-2 border-dashed transition-all duration-200"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg)',
|
...getBackgroundStyle('normal'),
|
||||||
borderColor: 'var(--accent-soft)'
|
borderColor: 'var(--accent-soft)'
|
||||||
}}>
|
}}>
|
||||||
<p style={{color: 'var(--text-muted)'}}>Zeichne deinen Traum hier (Canvas-Platzhalter)</p>
|
<p style={getTextStyle('muted')}>Zeichne deinen Traum hier (Canvas-Platzhalter)</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<div className="flex space-x-2">
|
<div className="flex space-x-2">
|
||||||
<button className="p-2 rounded-full transition-all duration-200 hover:transform hover:scale-110"
|
<button className="p-2 rounded-full transition-all duration-200 hover:transform hover:scale-110"
|
||||||
style={{backgroundColor: 'var(--accent-soft)', color: 'var(--text)'}}>
|
style={getAccentStyle(true)}>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||||
stroke="currentColor">
|
stroke="currentColor">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||||
@@ -121,7 +108,7 @@ export default function Home() {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button className="p-2 rounded-full transition-all duration-200 hover:transform hover:scale-110"
|
<button className="p-2 rounded-full transition-all duration-200 hover:transform hover:scale-110"
|
||||||
style={{backgroundColor: 'var(--accent-soft)', color: 'var(--text)'}}>
|
style={getAccentStyle(true)}>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||||
stroke="currentColor">
|
stroke="currentColor">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
|
||||||
@@ -130,15 +117,15 @@ export default function Home() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button className="px-4 py-2 rounded-lg transition-all duration-200 hover:transform hover:scale-105"
|
<button className="px-4 py-2 rounded-lg transition-all duration-200 hover:transform hover:scale-105"
|
||||||
style={{background: 'var(--accent-gradient)', color: 'white'}}>
|
style={getBackgroundStyle('accent-gradient')}>
|
||||||
Senden
|
Senden
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Personal Feed */}
|
{/* Personal Feed */}
|
||||||
<div className="dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01]"
|
<div className={getCardStyle().className}
|
||||||
style={{backgroundColor: 'var(--card)', color: 'var(--text)'}}>
|
style={getCardStyle()}>
|
||||||
<h3 className="font-bold mb-3 dream-title">Deine letzten Träume</h3>
|
<h3 className="font-bold mb-3 dream-title">Deine letzten Träume</h3>
|
||||||
{personalDreams.length > 0 ? (
|
{personalDreams.length > 0 ? (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
@@ -146,27 +133,26 @@ export default function Home() {
|
|||||||
<div key={dream.id}
|
<div key={dream.id}
|
||||||
className="p-3 rounded-lg transition-all duration-300 hover:transform hover:scale-[1.02]"
|
className="p-3 rounded-lg transition-all duration-300 hover:transform hover:scale-[1.02]"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg)',
|
...getBackgroundStyle('card'),
|
||||||
boxShadow: '0 4px 15px var(--shadow)',
|
|
||||||
animationDelay: `${index * 0.1}s`
|
animationDelay: `${index * 0.1}s`
|
||||||
}}>
|
}}>
|
||||||
<h4 className="font-medium" style={{color: 'var(--accent)'}}>{dream.title}</h4>
|
<h4 className="font-medium" style={getTextStyle('accent')}>{dream.title}</h4>
|
||||||
<p className="text-sm" style={{color: 'var(--text-muted)'}}>
|
<p className="text-sm" style={getTextStyle('muted')}>
|
||||||
{dream.date.toLocaleDateString('de-DE')}
|
{formatDateSimple(dream.date)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-sm" style={{color: 'var(--text-muted)'}}>
|
<p className="text-sm" style={getTextStyle('muted')}>
|
||||||
Du hast noch keine Träume aufgezeichnet. Starte jetzt!
|
Du hast noch keine Träume aufgezeichnet. Starte jetzt!
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Friends Feed */}
|
{/* Friends Feed */}
|
||||||
<div className="dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01]"
|
<div className={getCardStyle().className}
|
||||||
style={{backgroundColor: 'var(--card)', color: 'var(--text)'}}>
|
style={getCardStyle()}>
|
||||||
<h3 className="font-bold mb-3 dream-title">Träume von Freunden</h3>
|
<h3 className="font-bold mb-3 dream-title">Träume von Freunden</h3>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{friendsDreams.map((dream, index) => {
|
{friendsDreams.map((dream, index) => {
|
||||||
@@ -175,8 +161,7 @@ export default function Home() {
|
|||||||
<div key={dream.id}
|
<div key={dream.id}
|
||||||
className="p-3 rounded-lg transition-all duration-300 hover:transform hover:scale-[1.02]"
|
className="p-3 rounded-lg transition-all duration-300 hover:transform hover:scale-[1.02]"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--bg)',
|
...getBackgroundStyle('card'),
|
||||||
boxShadow: '0 4px 15px var(--shadow)',
|
|
||||||
animationDelay: `${index * 0.1}s`
|
animationDelay: `${index * 0.1}s`
|
||||||
}}>
|
}}>
|
||||||
<div className="flex items-center mb-1">
|
<div className="flex items-center mb-1">
|
||||||
@@ -191,15 +176,15 @@ export default function Home() {
|
|||||||
alt={dreamUser.name} className="w-full h-full object-cover"/>
|
alt={dreamUser.name} className="w-full h-full object-cover"/>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-xs"
|
<span className="text-xs"
|
||||||
style={{color: 'var(--text)'}}>{dreamUser?.name.charAt(0)}</span>
|
style={getTextStyle()}>{dreamUser?.name.charAt(0)}</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className="font-medium text-sm"
|
<span className="font-medium text-sm"
|
||||||
style={{color: 'var(--text)'}}>{dreamUser?.name}</span>
|
style={getTextStyle()}>{dreamUser?.name}</span>
|
||||||
</div>
|
</div>
|
||||||
<h4 className="font-medium" style={{color: 'var(--accent)'}}>{dream.title}</h4>
|
<h4 className="font-medium" style={getTextStyle('accent')}>{dream.title}</h4>
|
||||||
<p className="text-sm" style={{color: 'var(--text-muted)'}}>
|
<p className="text-sm" style={getTextStyle('muted')}>
|
||||||
{dream.date.toLocaleDateString('de-DE')}
|
{formatDateSimple(dream.date)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -208,19 +193,19 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Daily Highlights */}
|
{/* Daily Highlights */}
|
||||||
<div className="dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01]"
|
<div className={getCardStyle().className}
|
||||||
style={{backgroundColor: 'var(--card)', color: 'var(--text)'}}>
|
style={getCardStyle()}>
|
||||||
<h3 className="font-bold mb-3 dream-title">Tägliche Highlights</h3>
|
<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="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div className="p-3 rounded-lg"
|
<div className="p-3 rounded-lg"
|
||||||
style={{backgroundColor: 'var(--bg)', boxShadow: '0 4px 15px var(--shadow)'}}>
|
style={getBackgroundStyle('card')}>
|
||||||
<h4 className="font-medium mb-2" style={{color: 'var(--accent)'}}>Top Traumthemen</h4>
|
<h4 className="font-medium mb-2" style={getTextStyle('accent')}>Top Traumthemen</h4>
|
||||||
<ul className="list-disc pl-5 mb-4">
|
<ul className="list-disc pl-5 mb-4">
|
||||||
{topDreamTopics.map((topic, index) => (
|
{topDreamTopics.map((topic, index) => (
|
||||||
<li key={index}
|
<li key={index}
|
||||||
className="text-sm mb-1 transition-all duration-300 hover:transform hover:translate-x-1"
|
className="text-sm mb-1 transition-all duration-300 hover:transform hover:translate-x-1"
|
||||||
style={{color: 'var(--text)'}}>
|
style={getTextStyle()}>
|
||||||
<span style={{color: 'var(--accent-soft)'}}>{topic.label}:</span> {topic.percentage}%
|
<span style={{color: 'var(--accent-soft)'}}>{topic.label}:</span> {topic.percentage}%
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
@@ -228,13 +213,13 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-3 rounded-lg"
|
<div className="p-3 rounded-lg"
|
||||||
style={{backgroundColor: 'var(--bg)', boxShadow: '0 4px 15px var(--shadow)'}}>
|
style={getBackgroundStyle('card')}>
|
||||||
<h4 className="font-medium mb-2" style={{color: 'var(--accent)'}}>Stimmungskategorien</h4>
|
<h4 className="font-medium mb-2" style={getTextStyle('accent')}>Stimmungskategorien</h4>
|
||||||
<ul className="list-disc pl-5">
|
<ul className="list-disc pl-5">
|
||||||
{primaryMoodCategories.map((mood, index) => (
|
{primaryMoodCategories.map((mood, index) => (
|
||||||
<li key={index}
|
<li key={index}
|
||||||
className="text-sm mb-1 transition-all duration-300 hover:transform hover:translate-x-1"
|
className="text-sm mb-1 transition-all duration-300 hover:transform hover:translate-x-1"
|
||||||
style={{color: 'var(--text)'}}>
|
style={getTextStyle()}>
|
||||||
<span style={{color: 'var(--accent-soft)'}}>{mood.label}:</span> {mood.percentage}%
|
<span style={{color: 'var(--accent-soft)'}}>{mood.label}:</span> {mood.percentage}%
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
@@ -245,12 +230,8 @@ export default function Home() {
|
|||||||
|
|
||||||
{/* Ad Banner */}
|
{/* Ad Banner */}
|
||||||
<div
|
<div
|
||||||
className="dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01] floating"
|
className={getCardStyle(true).className}
|
||||||
style={{
|
style={getBackgroundStyle('gradient')}>
|
||||||
background: 'linear-gradient(135deg, var(--accent), var(--accent-dark))',
|
|
||||||
color: 'white',
|
|
||||||
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3)'
|
|
||||||
}}>
|
|
||||||
<div className="flex flex-col sm:flex-row items-center">
|
<div className="flex flex-col sm:flex-row items-center">
|
||||||
<div className="mb-4 sm:mb-0 sm:mr-4 transition-all duration-300 hover:transform hover:rotate-12">
|
<div className="mb-4 sm:mb-0 sm:mr-4 transition-all duration-300 hover:transform hover:rotate-12">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-16 w-16" fill="none" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-16 w-16" fill="none" viewBox="0 0 24 24"
|
||||||
|
83
src/styles/StyleUtils.ts
Normal file
83
src/styles/StyleUtils.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Utility functions for consistent styling across components
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base style for dreamy cards
|
||||||
|
* @param floating - Whether the card should have a floating animation
|
||||||
|
* @returns Object with style properties
|
||||||
|
*/
|
||||||
|
export const getCardStyle = (floating: boolean = false) => {
|
||||||
|
return {
|
||||||
|
backgroundColor: 'var(--card)',
|
||||||
|
color: 'var(--text)',
|
||||||
|
className: `dreamy-card p-4 mb-4 transition-all duration-300 hover:transform hover:scale-[1.01] ${floating ? 'floating' : ''}`
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the style for accent-colored elements
|
||||||
|
* @param soft - Whether to use the soft accent color
|
||||||
|
* @param isActive - Whether the element is in active state
|
||||||
|
* @returns Object with style properties
|
||||||
|
*/
|
||||||
|
export const getAccentStyle = (soft: boolean = false, isActive: boolean = true) => {
|
||||||
|
if (!isActive) {
|
||||||
|
return {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
color: 'var(--text)'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
backgroundColor: soft ? 'var(--accent-soft)' : 'var(--accent)',
|
||||||
|
color: soft ? 'var(--text)' : 'white'
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the style for text elements
|
||||||
|
* @param type - The type of text (normal, muted, accent)
|
||||||
|
* @returns Object with style properties
|
||||||
|
*/
|
||||||
|
export const getTextStyle = (type: 'normal' | 'muted' | 'accent' = 'normal') => {
|
||||||
|
switch (type) {
|
||||||
|
case 'muted':
|
||||||
|
return {color: 'var(--text-muted)'};
|
||||||
|
case 'accent':
|
||||||
|
return {color: 'var(--accent)'};
|
||||||
|
default:
|
||||||
|
return {color: 'var(--text)'};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the style for background elements
|
||||||
|
* @param type - The type of background (normal, card, gradient)
|
||||||
|
* @returns Object with style properties
|
||||||
|
*/
|
||||||
|
export const getBackgroundStyle = (type: 'normal' | 'card' | 'gradient' | 'accent-gradient' | 'topbar' = 'normal') => {
|
||||||
|
switch (type) {
|
||||||
|
case 'card':
|
||||||
|
return {backgroundColor: 'var(--bg)', boxShadow: '0 4px 15px var(--shadow)'};
|
||||||
|
case 'gradient':
|
||||||
|
return {
|
||||||
|
background: 'linear-gradient(135deg, var(--accent), var(--accent-dark))',
|
||||||
|
color: 'white',
|
||||||
|
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3)'
|
||||||
|
};
|
||||||
|
case 'accent-gradient':
|
||||||
|
return {
|
||||||
|
background: 'var(--accent-gradient)',
|
||||||
|
color: 'white',
|
||||||
|
boxShadow: '0 10px 30px var(--shadow), inset 0 0 15px rgba(166, 77, 255, 0.3)'
|
||||||
|
};
|
||||||
|
case 'topbar':
|
||||||
|
return {
|
||||||
|
background: 'var(--accent-gradient)',
|
||||||
|
boxShadow: '0 2px 10px var(--shadow)'
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {backgroundColor: 'var(--bg)'};
|
||||||
|
}
|
||||||
|
};
|
54
src/utils/DateUtils.ts
Normal file
54
src/utils/DateUtils.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Utility functions for date formatting
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date with full details including weekday and month names
|
||||||
|
* @param date - The date to format
|
||||||
|
* @returns Formatted date string (e.g., "Montag, 1. Januar 2023")
|
||||||
|
*/
|
||||||
|
export const formatDateFull = (date: Date): string => {
|
||||||
|
return date.toLocaleDateString('de-DE', {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date in a simple format
|
||||||
|
* @param date - The date to format
|
||||||
|
* @returns Formatted date string (e.g., "01.01.2023")
|
||||||
|
*/
|
||||||
|
export const formatDateSimple = (date: Date): string => {
|
||||||
|
return date.toLocaleDateString('de-DE');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date with time
|
||||||
|
* @param date - The date to format
|
||||||
|
* @returns Formatted date and time string (e.g., "01.01.2023, 14:30")
|
||||||
|
*/
|
||||||
|
export const formatDateWithTime = (date: Date): string => {
|
||||||
|
return date.toLocaleDateString('de-DE', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date in a numeric format without time
|
||||||
|
* @param date - The date to format
|
||||||
|
* @returns Formatted date string (e.g., "01.01.2023")
|
||||||
|
*/
|
||||||
|
export const formatDateNumeric = (date: Date): string => {
|
||||||
|
return date.toLocaleDateString('de-DE', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
});
|
||||||
|
};
|
Reference in New Issue
Block a user