Added 4 new themes and responsive Desktop support

This commit is contained in:
Anoy Roy Chowdhury
2025-08-06 02:30:46 +05:30
parent 948da0b7f1
commit c54285b947
5 changed files with 653 additions and 116 deletions
+313
View File
@@ -432,4 +432,317 @@
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
/* === PASTEL DREAM THEME === */
.theme-pastel-dream {
--background: 280 20% 98%;
--foreground: 240 10% 20%;
--card: 270 30% 96%;
--card-foreground: 240 10% 20%;
--popover: 270 30% 96%;
--popover-foreground: 240 10% 20%;
--primary: 280 80% 60%;
--primary-foreground: 280 20% 95%;
--secondary: 200 40% 70%;
--secondary-foreground: 240 10% 20%;
--muted: 270 20% 90%;
--muted-foreground: 240 10% 40%;
--accent: 320 70% 65%;
--accent-foreground: 280 20% 95%;
--destructive: 0 80% 60%;
--destructive-foreground: 280 20% 95%;
--border: 270 15% 80%;
--input: 270 15% 80%;
--ring: 280 80% 60%;
--radius: 0.75rem;
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
.theme-pastel-dream.dark {
--background: 280 10% 8%;
--foreground: 280 15% 85%;
--card: 280 12% 12%;
--card-foreground: 280 15% 85%;
--popover: 280 12% 12%;
--popover-foreground: 280 15% 85%;
--primary: 280 70% 55%;
--primary-foreground: 280 10% 95%;
--secondary: 200 50% 65%;
--secondary-foreground: 280 10% 95%;
--muted: 280 10% 15%;
--muted-foreground: 280 10% 60%;
--accent: 320 60% 60%;
--accent-foreground: 280 10% 95%;
--destructive: 0 70% 55%;
--destructive-foreground: 280 10% 95%;
--border: 280 10% 20%;
--input: 280 10% 20%;
--ring: 280 70% 55%;
}
/* === QUANTUM ROSE THEME === */
.theme-quantum-rose {
--background: 330 90% 97%;
--foreground: 320 20% 20%;
--card: 330 85% 95%;
--card-foreground: 320 20% 20%;
--popover: 330 85% 95%;
--popover-foreground: 320 20% 20%;
--primary: 320 85% 60%;
--primary-foreground: 330 20% 95%;
--secondary: 240 70% 70%;
--secondary-foreground: 320 20% 20%;
--muted: 330 50% 90%;
--muted-foreground: 320 20% 45%;
--accent: 180 70% 60%;
--accent-foreground: 330 20% 95%;
--destructive: 0 80% 60%;
--destructive-foreground: 330 20% 95%;
--border: 330 60% 85%;
--input: 330 60% 85%;
--ring: 320 85% 60%;
--radius: 1rem;
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
.theme-quantum-rose.dark {
--background: 320 20% 8%;
--foreground: 320 80% 85%;
--card: 320 25% 12%;
--card-foreground: 320 80% 85%;
--popover: 320 25% 12%;
--popover-foreground: 320 80% 85%;
--primary: 320 75% 60%;
--primary-foreground: 320 15% 95%;
--secondary: 240 80% 65%;
--secondary-foreground: 320 15% 95%;
--muted: 320 20% 15%;
--muted-foreground: 320 20% 60%;
--accent: 180 70% 55%;
--accent-foreground: 320 15% 95%;
--destructive: 0 75% 60%;
--destructive-foreground: 320 15% 95%;
--border: 320 20% 25%;
--input: 320 20% 25%;
--ring: 320 75% 60%;
}
/* === MODERN THEME (already defined, just fixing syntax) === */
.theme-modern {
--background: 223.8136 0% 100%;
--foreground: 223.8136 0% 3.9388%;
--card: 223.8136 0% 100%;
--card-foreground: 223.8136 0% 3.9388%;
--popover: 223.8136 0% 100%;
--popover-foreground: 223.8136 0% 3.9388%;
--primary: 223.8136 0% 9.0527%;
--primary-foreground: 223.8136 0% 98.0256%;
--secondary: 223.8136 0% 96.0587%;
--secondary-foreground: 223.8136 0% 9.0527%;
--muted: 223.8136 0% 96.0587%;
--muted-foreground: 223.8136 0% 45.1519%;
--accent: 223.8136 0% 96.0587%;
--accent-foreground: 223.8136 0% 9.0527%;
--destructive: 0 80% 60%;
--destructive-foreground: 223.8136 0% 98.0256%;
--border: 223.8136 0% 90%;
--input: 223.8136 0% 90%;
--ring: 223.8136 0% 9.0527%;
--radius: 0.5rem;
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
.theme-modern.dark {
--background: 223.8136 0% 3.9388%;
--foreground: 223.8136 0% 98.0256%;
--card: 223.8136 0% 7%;
--card-foreground: 223.8136 0% 98.0256%;
--popover: 223.8136 0% 7%;
--popover-foreground: 223.8136 0% 98.0256%;
--primary: 223.8136 0% 60%;
--primary-foreground: 223.8136 0% 10%;
--secondary: 223.8136 0% 12%;
--secondary-foreground: 223.8136 0% 98.0256%;
--muted: 223.8136 0% 10%;
--muted-foreground: 223.8136 0% 60%;
--accent: 223.8136 0% 12%;
--accent-foreground: 223.8136 0% 98.0256%;
--destructive: 0 80% 60%;
--destructive-foreground: 223.8136 0% 98.0256%;
--border: 223.8136 0% 15%;
--input: 223.8136 0% 15%;
--ring: 223.8136 0% 60%;
}
/* === TWITTER THEME === */
.theme-twitter {
--background: 205 100% 98%;
--foreground: 205 20% 20%;
--card: 205 100% 96%;
--card-foreground: 205 20% 20%;
--popover: 205 100% 96%;
--popover-foreground: 205 20% 20%;
--primary: 205 100% 50%;
--primary-foreground: 205 20% 95%;
--secondary: 0 0% 90%;
--secondary-foreground: 205 20% 20%;
--muted: 205 50% 90%;
--muted-foreground: 205 20% 50%;
--accent: 15 100% 60%;
--accent-foreground: 205 20% 95%;
--destructive: 0 80% 60%;
--destructive-foreground: 205 20% 95%;
--border: 205 80% 85%;
--input: 205 80% 85%;
--ring: 205 100% 50%;
--radius: 0.375rem;
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
.theme-twitter.dark {
--background: 205 20% 6%;
--foreground: 205 20% 90%;
--card: 205 25% 10%;
--card-foreground: 205 20% 90%;
--popover: 205 25% 10%;
--popover-foreground: 205 20% 90%;
--primary: 205 100% 55%;
--primary-foreground: 205 20% 95%;
--secondary: 0 0% 20%;
--secondary-foreground: 205 20% 90%;
--muted: 205 20% 15%;
--muted-foreground: 205 20% 60%;
--accent: 15 100% 65%;
--accent-foreground: 205 20% 95%;
--destructive: 0 80% 60%;
--destructive-foreground: 205 20% 95%;
--border: 205 20% 25%;
--input: 205 20% 25%;
--ring: 205 100% 55%;
}
/* === AMBER MINIMAL THEME === */
.theme-amber-minimal {
--background: 0 0% 100%;
--foreground: 0 0% 14.9020%;
--card: 0 0% 100%;
--card-foreground: 0 0% 14.9020%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 14.9020%;
--primary: 37.6923 92.1260% 50.1961%;
--primary-foreground: 0 0% 0%;
--secondary: 220.0000 14.2857% 95.8824%;
--secondary-foreground: 215 13.7931% 34.1176%;
--muted: 210 20.0000% 98.0392%;
--muted-foreground: 220 8.9362% 46.0784%;
--accent: 48.0000 100.0000% 96.0784%;
--accent-foreground: 22.7273 82.5000% 31.3725%;
--destructive: 0 84.2365% 60.1961%;
--destructive-foreground: 0 0% 100%;
--border: 220 13.0435% 90.9804%;
--input: 220 13.0435% 90.9804%;
--ring: 37.6923 92.1260% 50.1961%;
--chart-1: 37.6923 92.1260% 50.1961%;
--chart-2: 32.1327 94.6188% 43.7255%;
--chart-3: 25.9649 90.4762% 37.0588%;
--chart-4: 22.7273 82.5000% 31.3725%;
--chart-5: 21.7143 77.7778% 26.4706%;
--sidebar: 210 20.0000% 98.0392%;
--sidebar-foreground: 0 0% 14.9020%;
--sidebar-primary: 37.6923 92.1260% 50.1961%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 48.0000 100.0000% 96.0784%;
--sidebar-accent-foreground: 22.7273 82.5000% 31.3725%;
--sidebar-border: 220 13.0435% 90.9804%;
--sidebar-ring: 37.6923 92.1260% 50.1961%;
--font-sans: Inter, sans-serif;
--font-serif: Source Serif 4, serif;
--font-mono: JetBrains Mono, monospace;
--radius: 0.375rem;
--shadow-2xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05);
--shadow-xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05);
--shadow-sm: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
--shadow: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
--shadow-md: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 2px 4px -2px hsl(0 0% 0% / 0.10);
--shadow-lg: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 4px 6px -2px hsl(0 0% 0% / 0.10);
--shadow-xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 8px 10px -2px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
.theme-amber-minimal.dark {
--background: 0 0% 9.0196%;
--foreground: 0 0% 89.8039%;
--card: 0 0% 14.9020%;
--card-foreground: 0 0% 89.8039%;
--popover: 0 0% 14.9020%;
--popover-foreground: 0 0% 89.8039%;
--primary: 37.6923 92.1260% 50.1961%;
--primary-foreground: 0 0% 0%;
--secondary: 0 0% 14.9020%;
--secondary-foreground: 0 0% 89.8039%;
--muted: 0 0% 14.9020%;
--muted-foreground: 0 0% 63.9216%;
--accent: 22.7273 82.5000% 31.3725%;
--accent-foreground: 48 96.6387% 76.6667%;
--destructive: 0 84.2365% 60.1961%;
--destructive-foreground: 0 0% 100%;
--border: 0 0% 25.0980%;
--input: 0 0% 25.0980%;
--ring: 37.6923 92.1260% 50.1961%;
--chart-1: 43.2558 96.4126% 56.2745%;
--chart-2: 32.1327 94.6188% 43.7255%;
--chart-3: 22.7273 82.5000% 31.3725%;
--chart-4: 25.9649 90.4762% 37.0588%;
--chart-5: 22.7273 82.5000% 31.3725%;
--sidebar: 0 0% 5.8824%;
--sidebar-foreground: 0 0% 89.8039%;
--sidebar-primary: 37.6923 92.1260% 50.1961%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 22.7273 82.5000% 31.3725%;
--sidebar-accent-foreground: 48 96.6387% 76.6667%;
--sidebar-border: 0 0% 25.0980%;
--sidebar-ring: 37.6923 92.1260% 50.1961%;
--font-sans: Inter, sans-serif;
--font-serif: Source Serif 4, serif;
--font-mono: JetBrains Mono, monospace;
--radius: 0.375rem;
--shadow-2xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05);
--shadow-xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05);
--shadow-sm: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
--shadow: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
--shadow-md: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 2px 4px -2px hsl(0 0% 0% / 0.10);
--shadow-lg: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 4px 6px -2px hsl(0 0% 0% / 0.10);
--shadow-xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 8px 10px -2px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.25);
}
+234 -96
View File
@@ -6,7 +6,7 @@ import { DayNightCycle, AnimatedNumber } from "@/components/day-night-cycle";
import { AnimatedYear } from "@/components/animated-year";
import { WeeklyCalendar } from "@/components/weekly-calender";
import { TaskList } from "@/components/task-list";
import { Timer, Plus, BarChart3, Settings } from "lucide-react";
import { Timer, Plus, BarChart3, Settings, CheckCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { AddTaskModal } from "@/components/add-task-modal";
import { TaskOptionsModal } from "@/components/task-options-modal";
@@ -95,7 +95,15 @@ export default function Home() {
const root = document.documentElement;
// Remove all theme classes
root.classList.remove("theme-nature", "theme-neo-brutal", "theme-modern");
root.classList.remove(
"theme-nature",
"theme-neo-brutal",
"theme-modern",
"theme-pastel-dream",
"theme-quantum-rose",
"theme-twitter",
"theme-amber-minimal"
);
// Add current theme class (except for default)
if (theme !== "default") {
@@ -927,7 +935,8 @@ export default function Home() {
{!showIntroScreen && (
<div className="min-h-screen transition-colors duration-300 bg-background">
<div className="max-w-lg mx-auto min-h-screen px-4 relative overflow-hidden">
{/* Mobile/Tablet Layout (up to lg) */}
<div className="lg:hidden max-w-lg mx-auto min-h-screen px-4 relative overflow-hidden">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
@@ -985,7 +994,7 @@ export default function Home() {
/>
</div>
<div className="p-4 border-t border-dashed dark:border-gray-700 absolute bottom-0 left-1/2 -translate-x-1/2 bg-background/70 backdrop-blur-sm w-full z-50">
<div className="p-4 border-t border-dashed absolute bottom-0 left-1/2 -translate-x-1/2 bg-background/70 backdrop-blur-sm w-full z-50">
<div className="flex items-center justify-between">
<Button
onClick={() => setShowTimer(true)}
@@ -1021,99 +1030,228 @@ export default function Home() {
</div>
</div>
</motion.div>
<AnimatePresence>
{showSettings && (
<SettingsModal
onClose={() => setShowSettings(false)}
darkMode={darkMode}
onToggleDarkMode={() => setDarkMode(!darkMode)}
theme={theme}
onThemeChange={setTheme}
onExportData={exportData}
onImportData={importData}
onOpenWebRTCShare={() => setShowWebRTCShare(true)}
/>
)}
{showWebRTCShare && (
<WebRTCShareModal
onClose={() => setShowWebRTCShare(false)}
dailyTasks={dailyTasks}
customTags={customTags}
habits={habits}
darkMode={darkMode}
theme={theme}
onImportData={importDataFromWebRTC}
/>
)}
{showAddTask && (
<AddTaskModal
onClose={() => setShowAddTask(false)}
onAddTask={addTask}
customTags={customTags}
onAddCustomTag={addCustomTag}
selectedDate={selectedDate}
/>
)}
{showAddSubtask && parentTaskForSubtask && (
<AddSubtaskModal
onClose={() => {
setShowAddSubtask(false);
setParentTaskForSubtask(null);
}}
onAddSubtask={(title, tagId) => {
addSubtask(parentTaskForSubtask.id, title, tagId);
}}
customTags={customTags}
onAddCustomTag={addCustomTag}
parentTask={parentTaskForSubtask}
/>
)}
{showTaskOptions && selectedTask && (
<TaskOptionsModal
task={selectedTask}
customTags={customTags}
onClose={() => {
setShowTaskOptions(false);
setSelectedTask(null);
}}
onUpdateTask={updateTask}
onDeleteTask={deleteTask}
onAddCustomTag={addCustomTag}
onToggleTask={toggleTask}
selectedDate={selectedDate}
onTransferTask={transferTaskToCurrentDay}
currentActualDate={new Date()}
onAddSubtask={handleAddSubtask}
allTasks={allTasks}
/>
)}
{showHabits && (
<HabitTracker
habits={habits}
customTags={customTags}
onClose={() => setShowHabits(false)}
onUpdateHabits={setHabits}
onAddCustomTag={addCustomTag}
/>
)}
{showTimer && (
<TimerModal
tasks={flatTaskList} // Use flattened list for timer
onClose={() => setShowTimer(false)}
onUpdateTaskTime={updateTaskTime}
onUpdateTaskFocusTime={updateTaskFocusTime}
onToggleTask={toggleTask}
/>
)}
</AnimatePresence>
</div>
{/* Desktop Layout (lg and up) */}
<div className="hidden lg:flex max-h-screen h-screen overflow-hidden">
{/* Left Sidebar - Calendar & Navigation */}
<div className="w-lg border-r border-dashed flex flex-col bg-background/50 backdrop-blur-sm">
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.5 }}
className="flex flex-col h-full"
>
{/* Settings Button */}
<div className="p-6 border-b border-dashed flex items-center justify-between">
<div className="flex items-center gap-2 text-2xl font-extrabold">
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10">
<CheckCircle className="h-4 w-4 text-primary" />
</div>
Prio Space
</div>
<button
onClick={() => setShowSettings(true)}
className="bg-primary text-background rounded-lg py-3 px-4 hover:bg-primary/90 transition-colors"
>
<Settings className="h-4 w-4" />
</button>
</div>
{/* Date Header */}
<div className="p-4 border-b border-dashed px-6">
<div className="flex items-center justify-between">
<DayNightCycle selectedDate={selectedDate} />
<div className="flex items-center gap-2">
<div className="text-right flex flex-col">
<div className="text-xl font-extrabold flex items-center gap-2">
<AnimatedNumber
value={selectedDate.getDate()}
fontSize={20}
/>
{selectedDate.toLocaleDateString("en-US", {
month: "long",
})}
</div>
<div className="text-xl opacity-90 -mt-1 flex justify-end">
<AnimatedYear
year={selectedDate.getFullYear()}
fontSize={30}
/>
</div>
</div>
</div>
</div>
</div>
{/* Calendar */}
<div className="p-6 border-b border-dashed">
<WeeklyCalendar
selectedDate={selectedDate}
onDateSelect={setSelectedDate}
/>
</div>
{/* Desktop Action Buttons */}
<div className="p-6 space-y-4 flex-1">
<Button
onClick={() => setShowAddTask(true)}
size="lg"
className="w-full h-12 bg-primary hover:bg-primary/90 group hover:scale-[1.02] transition-all duration-200 [&_svg]:size-5 rounded-2xl"
>
<Plus className="h-5 w-5 mr-2 group-hover:scale-110 transition-transform" />
<span className="font-extrabold">Add Task</span>
</Button>
<Button
onClick={() => setShowTimer(true)}
variant="outline"
size="lg"
className="w-full h-12 font-bold hover:bg-accent/50 group hover:scale-[1.02] transition-all duration-200 rounded-2xl"
>
<Timer className="h-5 w-5 mr-2 group-hover:scale-110 transition-transform" />
<span className="font-extrabold">Timer</span>
</Button>
<Button
onClick={() => setShowHabits(true)}
variant="outline"
size="lg"
className="w-full h-12 font-bold hover:bg-accent/50 group hover:scale-[1.02] transition-all duration-200 rounded-2xl"
>
<BarChart3 className="h-5 w-5 mr-2 group-hover:scale-110 transition-transform" />
<span className="font-extrabold">Habits</span>
</Button>
</div>
{/* Keyboard shortcuts hint */}
<div className="p-6 pt-0 text-[10px] text-muted-foreground font-extrabold space-y-1 opacity-70">
<div>/Ctrl + A Add Task</div>
<div>/Ctrl + C Timer</div>
<div>/Ctrl + H Habits</div>
<div>/Ctrl + X Settings</div>
<div>Esc Close Modal</div>
</div>
</motion.div>
</div>
{/* Main Content Area */}
<div className="flex-1 flex flex-col">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.1 }}
className="flex-1 overflow-hidden relative"
>
{/* Task List */}
<div className="absolute top-0 left-0 h-full w-full overflow-auto hide-scroll">
<div className="p-6 mt-[4px]">
<TaskList
tasks={allTasks}
customTags={customTags}
onToggleTask={toggleTask}
onDeleteTask={deleteTask}
onTaskClick={handleTaskClick}
onAddSubtask={handleAddSubtask}
/>
</div>
</div>
</motion.div>
</div>
</div>
{/* Modals - Same for both layouts */}
<AnimatePresence>
{showSettings && (
<SettingsModal
onClose={() => setShowSettings(false)}
darkMode={darkMode}
onToggleDarkMode={() => setDarkMode(!darkMode)}
theme={theme}
onThemeChange={setTheme}
onExportData={exportData}
onImportData={importData}
onOpenWebRTCShare={() => setShowWebRTCShare(true)}
/>
)}
{showWebRTCShare && (
<WebRTCShareModal
onClose={() => setShowWebRTCShare(false)}
dailyTasks={dailyTasks}
customTags={customTags}
habits={habits}
darkMode={darkMode}
theme={theme}
onImportData={importDataFromWebRTC}
/>
)}
{showAddTask && (
<AddTaskModal
onClose={() => setShowAddTask(false)}
onAddTask={addTask}
customTags={customTags}
onAddCustomTag={addCustomTag}
selectedDate={selectedDate}
/>
)}
{showAddSubtask && parentTaskForSubtask && (
<AddSubtaskModal
onClose={() => {
setShowAddSubtask(false);
setParentTaskForSubtask(null);
}}
onAddSubtask={(title, tagId) => {
addSubtask(parentTaskForSubtask.id, title, tagId);
}}
customTags={customTags}
onAddCustomTag={addCustomTag}
parentTask={parentTaskForSubtask}
/>
)}
{showTaskOptions && selectedTask && (
<TaskOptionsModal
task={selectedTask}
customTags={customTags}
onClose={() => {
setShowTaskOptions(false);
setSelectedTask(null);
}}
onUpdateTask={updateTask}
onDeleteTask={deleteTask}
onAddCustomTag={addCustomTag}
onToggleTask={toggleTask}
selectedDate={selectedDate}
onTransferTask={transferTaskToCurrentDay}
currentActualDate={new Date()}
onAddSubtask={handleAddSubtask}
allTasks={allTasks}
/>
)}
{showHabits && (
<HabitTracker
habits={habits}
customTags={customTags}
onClose={() => setShowHabits(false)}
onUpdateHabits={setHabits}
onAddCustomTag={addCustomTag}
/>
)}
{showTimer && (
<TimerModal
tasks={flatTaskList} // Use flattened list for timer
onClose={() => setShowTimer(false)}
onUpdateTaskTime={updateTaskTime}
onUpdateTaskFocusTime={updateTaskFocusTime}
onToggleTask={toggleTask}
/>
)}
</AnimatePresence>
</div>
)}
</>
+55 -11
View File
@@ -4,6 +4,49 @@ import { useState, useEffect } from "react";
import { motion, useSpring } from "framer-motion";
import { Sun, Moon } from "lucide-react";
function AnimatedWeekday({ dayIndex, fontSize, textColor }) {
const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const height = fontSize * 1.2;
const animatedIndex = useSpring(dayIndex, { stiffness: 300, damping: 30 });
useEffect(() => {
animatedIndex.set(dayIndex);
}, [animatedIndex, dayIndex]);
return (
<div
className="relative overflow-hidden inline-block"
style={{
height: height,
width: fontSize * 2.2,
fontSize: fontSize,
color: textColor,
fontWeight: "800",
}}
>
{weekdays.map((day, index) => (
<motion.div
key={day}
className="absolute flex items-center justify-start font-extrabold"
style={{
y: useSpring((index - dayIndex) * height, {
stiffness: 300,
damping: 30,
}),
}}
animate={{
y: (index - dayIndex) * height,
}}
transition={{ type: "spring", stiffness: 300, damping: 30 }}
>
{day}
</motion.div>
))}
</div>
);
}
function AnimatedDigit({ value, fontSize, textColor }) {
const animatedValue = useSpring(value, { stiffness: 300, damping: 30 });
@@ -69,20 +112,21 @@ export function DayNightCycle({ selectedDate }) {
return date.toDateString() === today.toDateString();
};
// Get the day index (0 for Sunday, 1 for Monday, etc.) from the date
const dayIndex = selectedDate.getDay();
return (
<div className="flex items-center gap-3">
<div>
<div className="flex items-center gap-2">
<div className="text-4xl font-extrabold">
{selectedDate.toLocaleDateString("en-US", { weekday: "short" })}
</div>
{isToday(selectedDate) &&
(isDay ? (
<Sun className="h-7 w-7 text-yellow-500" />
) : (
<Moon className="h-7 w-7 text-blue-500" />
))}
<div className="flex items-center gap-2">
<div className="text-4xl font-extrabold flex items-center">
<AnimatedWeekday dayIndex={dayIndex} fontSize={32} />
</div>
{isToday(selectedDate) &&
(isDay ? (
<Sun className="h-7 w-7 text-yellow-500" />
) : (
<Moon className="h-7 w-7 text-blue-500" />
))}
</div>
</div>
);
+43 -3
View File
@@ -68,6 +68,46 @@ export function SettingsModal({
background: "#FFFFFF",
},
},
{
id: "pastel-dream",
name: "Pastel Dream",
description: "Soft lavender & pink tones",
preview: {
primary: "#D67AD2",
secondary: "#A2DCEF",
background: "#F8F4FF",
},
},
{
id: "quantum-rose",
name: "Quantum Rose",
description: "Vibrant pink & teal fusion",
preview: {
primary: "#D93A7D",
secondary: "#2DD8C6",
background: "#FFF5FA",
},
},
{
id: "twitter",
name: "Twitter",
description: "Blues & clean contrast",
preview: {
primary: "#1DA1F2",
secondary: "#F7F9F9",
background: "#F5F8FA",
},
},
{
id: "amber-minimal",
name: "Amber Minimal",
description: "Clean amber & white minimalism",
preview: {
primary: "#F59E0B",
secondary: "#E0E7FF",
background: "#FFFFFF",
},
},
];
// Animation variants
@@ -276,7 +316,7 @@ export function SettingsModal({
</div>
</div>
</div>
<div className="flex gap-2">
<div className="grid grid-cols-4 gap-2">
{themes.map((themeData) => (
<motion.button
key={themeData.id}
@@ -481,10 +521,10 @@ export function SettingsModal({
>
<div className="text-center space-y-3">
<div className="text-lg font-extrabold text-primary">
Prio Space V1.2.0
Prio Space V1.3.0
</div>
<div className="text-sm font-bold text-gray-600 dark:text-gray-300 uppercase tracking-wider">
Focus Track Share Achieve
Focus Track Achieve
</div>
{/* vibecoded section */}
+8 -6
View File
@@ -425,12 +425,14 @@ function TaskItem({
}
${isLastTask && (!hasSubtasks || !isExpanded) ? "border-b" : ""}`}
style={{ paddingLeft: `${paddingLeft}px` }}
onClick={(e) => onTaskClick(task, e)}
whileHover={{ scale: 1.01 }}
whileHover={{ scale: 1.0 }}
whileTap={{ scale: 0.98 }}
>
<div className="flex items-center justify-between relative z-10 p-4">
<div className="flex items-center gap-3 flex-1">
<div className="flex items-center justify-between relative z-10">
<div
className="flex items-center gap-3 flex-1 p-4"
onClick={(e) => onTaskClick(task, e)}
>
{/* Expand/Collapse button for main tasks with subtasks */}
{hasSubtasks && !isSubtask && (
<motion.button
@@ -528,10 +530,10 @@ function TaskItem({
{/* Completion Circle */}
<motion.button
onClick={(e) => onToggleTask(task.id, e)}
className={`flex-shrink-0 w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all duration-200 ${
className={`flex-shrink-0 w-6 h-6 rounded-full border-2 flex items-center justify-center transition-all duration-200 mr-4 ${
task.completed
? "bg-primary border-primary"
: "border-primary/30 hover:border-primary hover:bg-primary/10 border-dotted"
: "border-primary/50 hover:border-primary hover:bg-primary/10 border-dotted"
}`}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}