diff --git a/index.html b/index.html index d4da836..1ff5dfe 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,9 @@ - REMind + + + REMind | Dream Tracker
diff --git a/src/App.css b/src/App.css index b9d355d..4960491 100644 --- a/src/App.css +++ b/src/App.css @@ -1,21 +1,24 @@ #root { - max-width: 1280px; + width: 100%; margin: 0 auto; - padding: 2rem; + padding: 0; text-align: center; } +.App { + min-height: 100vh; + background-color: var(--bg); + color: var(--text); + transition: background-color 0.3s, color 0.3s; +} + .logo { height: 6em; - padding: 1.5em; will-change: filter; transition: filter 300ms; } .logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); + filter: drop-shadow(0 0 2em var(--accent)); } @keyframes logo-spin { @@ -34,9 +37,54 @@ } .card { - padding: 2em; + padding: 1.5em; + background-color: var(--card); + border-radius: 12px; + box-shadow: 0 4px 12px var(--shadow); + margin-bottom: 1rem; + transition: transform 0.2s, box-shadow 0.2s; } -.read-the-docs { - color: #888; +.card:hover { + transform: translateY(-3px); + box-shadow: 0 6px 16px var(--shadow); +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .card { + padding: 1em; + } +} + +/* Dreamy effects */ +.dreamy-text { + background: var(--accent-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-weight: bold; +} + +.dreamy-border { + border: 2px solid transparent; + background: + linear-gradient(var(--bg), var(--bg)) padding-box, + var(--accent-gradient) border-box; + border-radius: 12px; +} + +.dreamy-button { + background: var(--accent-gradient); + color: white; + border: none; + padding: 0.6em 1.2em; + border-radius: 8px; + font-weight: 500; + transition: transform 0.2s, box-shadow 0.2s; + box-shadow: 0 4px 12px var(--shadow); +} + +.dreamy-button:hover { + transform: translateY(-2px); + box-shadow: 0 6px 16px var(--shadow); } diff --git a/src/App.tsx b/src/App.tsx index 5c4a5e4..39ade64 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,43 +1,175 @@ import './App.css'; +import {useState} from 'react'; import Navbar from './components/Navbar'; import TopBar from './components/TopBar'; +import SplashScreen from './components/SplashScreen'; import {BrowserRouter, Route, Routes} from 'react-router-dom'; import Feed from "./pages/Feed.tsx"; import DreamPage from "./pages/DreamPage.tsx"; +import ProfilePage from "./pages/ProfilePage.tsx"; function Home() { - return
Home Page
; + return ( +
+

Welcome to REMind

+

Your dreamy journey to better sleep and dream tracking

+ +
+

Track Your Dreams

+

Record and analyze your dreams with our intuitive interface

+ +
+ +
+
+

Dream Journal

+

Keep track of all your dreams in one place

+
+
+

Sleep Analysis

+

Understand your sleep patterns better

+
+
+
+ ); } function Record() { - return
Record Page
; + return ( +
+

Record Your Dream

+ +
+
+
+ + + +
+

Tap to start recording your dream

+

+ Your voice will be transcribed automatically +

+
+ +
+ +
+ + +
+
+ ); } function Archive() { - return
Archive Page
; -} - -function Profile() { - return
Profile Page
; -} - -export default function App() { return ( - -
- -
- - - }/> - }/> - }/> - }/> - }/> - }/> - +
+

Dream Archive

+ +
+
+ +
+
+
- + +
+ {[1, 2, 3].map((item) => ( +
+
+

+ Dream #{item} +

+ + {new Date().toLocaleDateString()} + +
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Vivamus lacinia, nunc eu tincidunt faucibus... +

+
+ +
+
+ ))} +
+
+ ); +} + + +export default function App() { + const [isLoading, setIsLoading] = useState(true); + + const handleSplashFinished = () => { + setIsLoading(false); + }; + + if (isLoading) { + return ; + } + + return ( +
+ +
+ +
+ +
+ + }/> + }/> + }/> + }/> + }/> + }/> + +
+
+
+
+
); } diff --git a/src/assets/logo.svg b/src/assets/logo.svg index b38fb4c..bcd4c73 100644 --- a/src/assets/logo.svg +++ b/src/assets/logo.svg @@ -1,8 +1,8 @@ - - + + diff --git a/src/assets/text.svg b/src/assets/text.svg index 52a3ef5..5d04166 100644 --- a/src/assets/text.svg +++ b/src/assets/text.svg @@ -4,8 +4,8 @@ @import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap'); - - + + diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index fd15d80..8c78c60 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -2,30 +2,31 @@ import {NavLink} from 'react-router-dom'; import {FaArchive, FaHome, FaList, FaMicrophone, FaUser} from "react-icons/fa"; export default function Navbar() { - return (<>
- - +
+ + - - + + - + ); diff --git a/src/components/SplashScreen.tsx b/src/components/SplashScreen.tsx new file mode 100644 index 0000000..15cfc1c --- /dev/null +++ b/src/components/SplashScreen.tsx @@ -0,0 +1,31 @@ +import { useEffect } from 'react'; +import logo from '../assets/logo.svg'; +import text from '../assets/text.svg'; + +interface SplashScreenProps { + onFinished: () => void; +} + +export default function SplashScreen({ onFinished }: SplashScreenProps) { + useEffect(() => { + // Simulate loading time with a timeout + const timer = setTimeout(() => { + onFinished(); + }, 2000); // Show splash screen for 2 seconds + + return () => clearTimeout(timer); + }, [onFinished]); + + return ( +
+
+ REMind Logo + REMind Text +
+
+
+

Loading your dreams...

+
+
+ ); +} \ No newline at end of file diff --git a/src/components/TopBar.tsx b/src/components/TopBar.tsx index 20cb6bd..1a26b81 100644 --- a/src/components/TopBar.tsx +++ b/src/components/TopBar.tsx @@ -5,13 +5,41 @@ import text from '../assets/text.svg'; export default function TopBar() { const [visible, setVisible] = useState(true); const [lastScrollY, setLastScrollY] = useState(0); + const [darkMode, setDarkMode] = useState(false); + + // Function to update theme meta tag + const updateThemeColor = (isDark: boolean) => { + const themeColor = isDark ? '#bb86fc' : '#9d4eff'; + const metaThemeColor = document.querySelector('meta[name="theme-color"]'); + if (metaThemeColor) { + metaThemeColor.setAttribute('content', themeColor); + } + }; + + // Initialize theme based on user preference or system preference + useEffect(() => { + const isDarkMode = localStorage.getItem('darkMode') === 'true' || + window.matchMedia('(prefers-color-scheme: dark)').matches; + setDarkMode(isDarkMode); + document.documentElement.setAttribute('data-theme', isDarkMode ? 'dark' : 'light'); + updateThemeColor(isDarkMode); + }, []); + + // Function to toggle theme + const toggleTheme = () => { + const newDarkMode = !darkMode; + setDarkMode(newDarkMode); + document.documentElement.setAttribute('data-theme', newDarkMode ? 'dark' : 'light'); + localStorage.setItem('darkMode', newDarkMode.toString()); + updateThemeColor(newDarkMode); + }; useEffect(() => { const handleScroll = () => { const currentScrollY = window.scrollY; // Hide the topbar when scrolling down, show when scrolling up - if (currentScrollY > lastScrollY) { + if (currentScrollY > lastScrollY && currentScrollY > 50) { setVisible(false); } else { setVisible(true); @@ -29,13 +57,39 @@ export default function TopBar() { return (
-
- REMind Logo - REMind Text +
+
+ REMind Logo + REMind Text +
+ +
); diff --git a/src/data/MockUsers.ts b/src/data/MockUsers.ts index 087bb5b..5891d2b 100644 --- a/src/data/MockUsers.ts +++ b/src/data/MockUsers.ts @@ -1,11 +1,12 @@ import User from "../types/User.ts"; export const MockUsers: User[] = [ - new User(1, "Matthias", "matthias.jpg"), - new User(2, "Kim", "kim.png"), - new User(3, "Anja", "anja.png"), + new User(1, "Matthias", "matthias.jpg", "s4mapuch@uni-trier.de", 42, 7), + new User(2, "Kim", "kim.png", "kim@example.com", 28, 3), + new User(3, "Anja", "anja.png", "anja@example.com", 15, 5), + new User(4, "Neo Quantum", "neo.png", "neo@remind.dev", 64, 12), ] export const MockUserMap: Map = new Map(MockUsers.map(user => [user.id, user])); -export default MockUsers; \ No newline at end of file +export default MockUsers; diff --git a/src/index.css b/src/index.css index 5960035..8954949 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,16 @@ @import "tailwindcss"; :root { - --bg: #f9f6ff; + --bg: #f8f5ff; --container: #ede6fa; - --card: #d6c6ff; + --card: #e0d4ff; --text: #1e102e; --text-muted: #4a375e; - --accent: #7f39fb; - --accent-gradient: linear-gradient(135deg, #7f39fb, #d500f9); + --accent: #9d4eff; + --accent-gradient: linear-gradient(135deg, #9d4eff, #d500f9); + --accent-soft: #c9a4ff; + --accent-dark: #6a0dad; + --shadow: rgba(157, 78, 255, 0.2); font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; line-height: 1.5; @@ -24,13 +27,16 @@ } [data-theme="dark"] { - --bg: #1e102e; - --container: #3a1a5d; - --card: #5c2d91; + --bg: #1a0933; + --container: #2d1155; + --card: #3d1a6e; --text: #f5e6ff; --text-muted: #c9a4e3; --accent: #bb86fc; - --accent-gradient: linear-gradient(135deg, #7f39fb, #d500f9); + --accent-gradient: linear-gradient(135deg, #bb86fc, #d500f9); + --accent-soft: #9d4eff; + --accent-dark: #6a0dad; + --shadow: rgba(187, 134, 252, 0.3); } .border-background { @@ -69,12 +75,13 @@ a:hover { body { margin: 0; display: flex; - place-items: center; min-width: 320px; min-height: 100vh; + width: 100%; background-color: var(--bg); color: var(--text); transition: background-color 0.3s, color 0.3s; + overflow-x: hidden; } h1 { @@ -173,3 +180,75 @@ button:focus-visible { .theme-toggle input:checked + .slider { background-color: var(--accent); } + +/* Dreamy violet enhancements */ +.dream-title { + font-size: 1.5rem; + font-weight: bold; + background: var(--accent-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + margin-bottom: 0.5rem; +} + +.dream-container { + background-color: var(--container); + border-radius: 16px; + padding: 1.5rem; + margin-bottom: 1.5rem; + box-shadow: 0 4px 15px var(--shadow); + transition: transform 0.3s, box-shadow 0.3s; +} + +.dream-container:hover { + transform: translateY(-5px); + box-shadow: 0 8px 25px var(--shadow); +} + +/* Scrollbar styling */ +::-webkit-scrollbar { + width: 10px; +} + +::-webkit-scrollbar-track { + background: var(--bg); +} + +::-webkit-scrollbar-thumb { + background: var(--accent-soft); + border-radius: 5px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--accent); +} + +/* Animations */ +@keyframes dream-float { + 0% { + transform: translateY(0); + } + 50% { + transform: translateY(-10px); + } + 100% { + transform: translateY(0); + } +} + +.floating { + animation: dream-float 6s ease-in-out infinite; +} + +/* Responsive typography */ +@media (max-width: 768px) { + h1 { + font-size: 2.5em; + } + h2 { + font-size: 1.8em; + } + p { + font-size: 0.95em; + } +} diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx new file mode 100644 index 0000000..110ec1f --- /dev/null +++ b/src/pages/ProfilePage.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { MockUsers } from '../data/MockUsers'; + +const ProfilePage: React.FC = () => { + // Find Neo Quantum in MockUsers + const profileUser = MockUsers.find(user => user.name === "Neo Quantum"); + + // Default values if user not found + const defaultName = "TestUser"; + const defaultEmail = "user@example.com"; + const defaultDreamCount = 0; + const defaultStreakDays = 0; + + return ( +
+
+ {/* Profile Picture */} +
+ {profileUser +
+ + {/* User Information */} +
+

{profileUser ? profileUser.name : defaultName}

+

{profileUser ? profileUser.email : defaultEmail}

+ +
+
+

{profileUser ? profileUser.dreamCount : defaultDreamCount}

+

Dreams

+
+
+

{profileUser ? profileUser.streakDays : defaultStreakDays}

+

Days Streak

+
+
+ +
+

Account Settings

+
+
+ Notifications + +
+
+ Privacy + +
+
+
+
+
+
+ ); +}; + +export default ProfilePage; diff --git a/src/types/User.ts b/src/types/User.ts index e483dcb..19978b9 100644 --- a/src/types/User.ts +++ b/src/types/User.ts @@ -2,14 +2,23 @@ export default class User { id: number; name: string; profilePicture: string; + email: string; + dreamCount: number; + streakDays: number; constructor( id: number, name: string, - profilePicture: string + profilePicture: string, + email: string = "", + dreamCount: number = 0, + streakDays: number = 0 ){ this.id = id this.name = name this.profilePicture = profilePicture + this.email = email + this.dreamCount = dreamCount + this.streakDays = streakDays } -} \ No newline at end of file +}