mirror of
https://github.com/harivansh-afk/Saas-Teamspace.git
synced 2026-04-20 15:01:26 +00:00
changed a lot
This commit is contained in:
parent
ef9ccf22d3
commit
28901128ff
20 changed files with 1794 additions and 526 deletions
|
|
@ -15,13 +15,15 @@ import { Input } from '@/components/ui/input'
|
|||
import { CardWrapper } from '@/components/auth/card-wrapper'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import Link from 'next/link'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import { useSearchParams, useRouter } from 'next/navigation'
|
||||
import { useEffect, useRef, useTransition } from 'react'
|
||||
import { login } from '@/actions/login'
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams()
|
||||
const callbackUrl = searchParams.get('callbackUrl')
|
||||
const urlError =
|
||||
searchParams.get('error') === 'OAuthAccountNotLinked'
|
||||
? 'Email already in use with different provider!'
|
||||
|
|
@ -52,8 +54,12 @@ export default function Page() {
|
|||
}
|
||||
if (data?.success) {
|
||||
toast.success(data.success)
|
||||
form.reset({ email: '', password: '' })
|
||||
window.location.href = '/'
|
||||
if (data.success === 'Confirmation email sent!') {
|
||||
// Don't redirect if we're just sending a confirmation email
|
||||
return;
|
||||
}
|
||||
router.push('/dashboard');
|
||||
router.refresh();
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import { newVerification } from '@/actions/new-verification'
|
|||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { toast } from 'react-hot-toast'
|
||||
import { Loader2 } from 'lucide-react'
|
||||
|
||||
export default function NewVerificationForm() {
|
||||
const [error, setError] = useState<string | undefined>()
|
||||
const [success, setSuccess] = useState<string | undefined>()
|
||||
const [hasErrorToastShown, setHasErrorToastShown] = useState<boolean>(false)
|
||||
|
||||
const searchParams = useSearchParams()
|
||||
const token = searchParams.get('token')
|
||||
|
|
@ -17,25 +17,25 @@ export default function NewVerificationForm() {
|
|||
|
||||
const onSubmit = useCallback(() => {
|
||||
if (!token) {
|
||||
toast.error('No token provided')
|
||||
setError('Missing token!')
|
||||
return
|
||||
}
|
||||
|
||||
newVerification(token)
|
||||
.then((data) => {
|
||||
if (data?.error) {
|
||||
setTimeout(() => {
|
||||
setError(data.error)
|
||||
}, 500)
|
||||
} else if (data?.success) {
|
||||
setError(data.error)
|
||||
}
|
||||
if (data?.success) {
|
||||
setSuccess(data.success)
|
||||
toast.success(data.success)
|
||||
setTimeout(() => {
|
||||
router.push('/login')
|
||||
}, 100)
|
||||
}, 2000)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
const errorMessage = 'Something went wrong'
|
||||
setError(errorMessage)
|
||||
setError('Something went wrong!')
|
||||
})
|
||||
}, [token, router])
|
||||
|
||||
|
|
@ -43,24 +43,37 @@ export default function NewVerificationForm() {
|
|||
onSubmit()
|
||||
}, [onSubmit])
|
||||
|
||||
useEffect(() => {
|
||||
if (error && !hasErrorToastShown) {
|
||||
const timer = setTimeout(() => {
|
||||
toast.error(error)
|
||||
setHasErrorToastShown(true)
|
||||
}, 100)
|
||||
return () => clearTimeout(timer) // Cleanup the timeout if component unmounts
|
||||
}
|
||||
}, [error, hasErrorToastShown])
|
||||
|
||||
return (
|
||||
<CardWrapper
|
||||
headerTitle="Verify your email"
|
||||
backButtonLabel="Back to Login"
|
||||
headerTitle="Confirm your email"
|
||||
backButtonLabel="Back to login"
|
||||
backButtonHref="/login"
|
||||
>
|
||||
<div className="flex items-center w-full justify-center">
|
||||
{!success && !error && <p>Verifying...</p>}
|
||||
{!success && !error && (
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Verifying your email...
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{success && (
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<p className="text-success text-sm">{success}</p>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Redirecting to login...
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<p className="text-destructive text-sm">{error}</p>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Please try again or contact support.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardWrapper>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<main className="max-w-6xl w-full flex items-center justify-center px-6">
|
||||
{children}
|
||||
</main>
|
||||
)
|
||||
import { Metadata } from "next"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Dashboard",
|
||||
description: "Task management and team collaboration dashboard",
|
||||
}
|
||||
|
||||
export default DashboardLayout
|
||||
export default function DashboardLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return children
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,62 +1,151 @@
|
|||
import { Metadata } from 'next'
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Calendar,
|
||||
CheckCircle2,
|
||||
Clock,
|
||||
ListTodo,
|
||||
Plus,
|
||||
UserRoundCheck
|
||||
} from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card } from '@/components/ui/card'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { auth } from '@/auth'
|
||||
import { redirect } from 'next/navigation'
|
||||
import { db } from '@/lib/db'
|
||||
Search,
|
||||
Bell,
|
||||
Mail,
|
||||
Settings,
|
||||
} from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card } from "@/components/ui/card"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { ProjectSelect } from "@/components/project-select"
|
||||
import { TaskColumn } from "@/components/task-column"
|
||||
import { RichTextEditor } from "@/components/rich-text-editor"
|
||||
import { FileUpload } from "@/components/file-upload"
|
||||
import {
|
||||
DndContext,
|
||||
DragEndEvent,
|
||||
DragOverlay,
|
||||
DragStartEvent,
|
||||
MouseSensor,
|
||||
TouchSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from "@dnd-kit/core"
|
||||
import { useState } from "react"
|
||||
import { TaskCard } from "@/components/task-card"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Dashboard',
|
||||
description: 'Task management and team collaboration dashboard'
|
||||
interface Task {
|
||||
id: string
|
||||
title: string
|
||||
status: string
|
||||
dueDate: string
|
||||
progress: number
|
||||
}
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const session = await auth()
|
||||
export default function DashboardPage() {
|
||||
const [tasks, setTasks] = useState<Task[]>([
|
||||
{ id: "1", title: "Design new landing page", status: "In Progress", dueDate: "2023-12-01", progress: 60 },
|
||||
{ id: "2", title: "Implement authentication", status: "Todo", dueDate: "2023-12-05", progress: 0 },
|
||||
{ id: "3", title: "Write documentation", status: "Done", dueDate: "2023-11-30", progress: 100 },
|
||||
])
|
||||
|
||||
if (!session) {
|
||||
redirect('/login')
|
||||
const [activeTask, setActiveTask] = useState<Task | null>(null)
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(MouseSensor, {
|
||||
activationConstraint: {
|
||||
distance: 8,
|
||||
},
|
||||
}),
|
||||
useSensor(TouchSensor, {
|
||||
activationConstraint: {
|
||||
delay: 300,
|
||||
tolerance: 8,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
const handleDragStart = (event: DragStartEvent) => {
|
||||
const { active } = event
|
||||
const task = tasks.find(t => t.id === active.id)
|
||||
if (task) {
|
||||
setActiveTask(task)
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch tasks (placeholder - implement actual DB queries)
|
||||
const tasks = [
|
||||
{ id: 1, title: 'Design new landing page', status: 'In Progress', dueDate: '2023-12-01', progress: 60 },
|
||||
{ id: 2, title: 'Implement authentication', status: 'Todo', dueDate: '2023-12-05', progress: 0 },
|
||||
{ id: 3, title: 'Write documentation', status: 'Done', dueDate: '2023-11-30', progress: 100 }
|
||||
]
|
||||
const handleDragEnd = (event: DragEndEvent) => {
|
||||
const { active, over } = event
|
||||
|
||||
if (over && active.id !== over.id) {
|
||||
setTasks(tasks => {
|
||||
const oldIndex = tasks.findIndex(t => t.id === active.id)
|
||||
const task = tasks[oldIndex]
|
||||
const newStatus = over.id as string
|
||||
|
||||
if (task && (newStatus === "Todo" || newStatus === "In Progress" || newStatus === "Done")) {
|
||||
const updatedTasks = [...tasks]
|
||||
updatedTasks[oldIndex] = { ...task, status: newStatus }
|
||||
return updatedTasks
|
||||
}
|
||||
|
||||
return tasks
|
||||
})
|
||||
}
|
||||
|
||||
setActiveTask(null)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-1 space-y-4 p-4 md:p-8 pt-6">
|
||||
<div className="flex items-center justify-between space-y-2">
|
||||
<h2 className="text-3xl font-bold tracking-tight">Dashboard</h2>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Add New Task
|
||||
</Button>
|
||||
<div className="flex min-h-screen">
|
||||
{/* Sidebar */}
|
||||
<aside className="w-64 border-r bg-card">
|
||||
<div className="p-6">
|
||||
<h2 className="text-lg font-semibold">Shadcn UI Kit</h2>
|
||||
</div>
|
||||
</div>
|
||||
<nav className="px-4 space-y-2">
|
||||
<Button variant="ghost" className="w-full justify-start">
|
||||
<ListTodo className="mr-2 h-4 w-4" />
|
||||
Dashboard
|
||||
</Button>
|
||||
<Button variant="ghost" className="w-full justify-start">
|
||||
<Mail className="mr-2 h-4 w-4" />
|
||||
Messages
|
||||
</Button>
|
||||
<Button variant="ghost" className="w-full justify-start">
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
Settings
|
||||
</Button>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<Tabs defaultValue="overview" className="space-y-4">
|
||||
<TabsList>
|
||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||
<TabsTrigger value="tasks">Tasks</TabsTrigger>
|
||||
<TabsTrigger value="calendar">Calendar</TabsTrigger>
|
||||
</TabsList>
|
||||
{/* Main Content */}
|
||||
<main className="flex-1">
|
||||
{/* Header */}
|
||||
<header className="border-b">
|
||||
<div className="flex h-16 items-center px-6 gap-4">
|
||||
<ProjectSelect />
|
||||
<div className="flex-1">
|
||||
<form>
|
||||
<div className="relative">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search..."
|
||||
className="w-full bg-background pl-8 md:w-[300px]"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon">
|
||||
<Bell className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<TabsContent value="overview" className="space-y-4">
|
||||
{/* Dashboard Content */}
|
||||
<div className="p-6 space-y-6">
|
||||
{/* Stats */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<Card className="p-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<ListTodo className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">Total Tasks</span>
|
||||
</div>
|
||||
|
|
@ -65,7 +154,7 @@ export default async function DashboardPage() {
|
|||
</Card>
|
||||
<Card className="p-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">In Progress</span>
|
||||
</div>
|
||||
|
|
@ -74,7 +163,7 @@ export default async function DashboardPage() {
|
|||
</Card>
|
||||
<Card className="p-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle2 className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">Completed</span>
|
||||
</div>
|
||||
|
|
@ -83,218 +172,77 @@ export default async function DashboardPage() {
|
|||
</Card>
|
||||
<Card className="p-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<UserRoundCheck className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">Team Members</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Calendar className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">Upcoming</span>
|
||||
</div>
|
||||
<div className="text-2xl font-bold">6</div>
|
||||
<div className="text-2xl font-bold">3</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-7">
|
||||
<Card className="col-span-4">
|
||||
<div className="p-6">
|
||||
<h3 className="text-lg font-medium">Recent Tasks</h3>
|
||||
<div className="mt-4 space-y-4">
|
||||
{tasks.map(task => (
|
||||
<div key={task.id} className="flex items-center justify-between border-b pb-4">
|
||||
<div>
|
||||
<h4 className="font-medium">{task.title}</h4>
|
||||
<p className="text-sm text-muted-foreground">Due: {task.dueDate}</p>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<span className="text-sm">{task.status}</span>
|
||||
<div className="h-2 w-24 bg-gray-200 rounded-full">
|
||||
<div
|
||||
className="h-full bg-blue-500 rounded-full"
|
||||
style={{ width: `${task.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
{/* Task Board */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-2xl font-bold tracking-tight">Tasks</h2>
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Add Task
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card className="col-span-3">
|
||||
<div className="p-6">
|
||||
<h3 className="text-lg font-medium">Upcoming Deadlines</h3>
|
||||
<div className="mt-4 space-y-4">
|
||||
<div className="flex items-center space-x-4">
|
||||
<Calendar className="h-4 w-4 text-muted-foreground" />
|
||||
<div>
|
||||
<p className="font-medium">Design Review</p>
|
||||
<p className="text-sm text-muted-foreground">Tomorrow at 2:00 PM</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<Calendar className="h-4 w-4 text-muted-foreground" />
|
||||
<div>
|
||||
<p className="font-medium">Team Meeting</p>
|
||||
<p className="text-sm text-muted-foreground">Friday at 10:00 AM</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<TaskColumn
|
||||
id="Todo"
|
||||
title="Todo"
|
||||
icon={ListTodo}
|
||||
tasks={tasks.filter(t => t.status === "Todo")}
|
||||
/>
|
||||
<TaskColumn
|
||||
id="In Progress"
|
||||
title="In Progress"
|
||||
icon={Clock}
|
||||
tasks={tasks.filter(t => t.status === "In Progress")}
|
||||
/>
|
||||
<TaskColumn
|
||||
id="Done"
|
||||
title="Done"
|
||||
icon={CheckCircle2}
|
||||
tasks={tasks.filter(t => t.status === "Done")}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="tasks" className="space-y-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<h3 className="text-lg font-medium">All Tasks</h3>
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
New Task
|
||||
</Button>
|
||||
<DragOverlay>
|
||||
{activeTask ? <TaskCard {...activeTask} /> : null}
|
||||
</DragOverlay>
|
||||
</DndContext>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Todo Column */}
|
||||
<Card className="p-4">
|
||||
<h4 className="font-medium mb-4 flex items-center">
|
||||
<ListTodo className="h-4 w-4 mr-2" />
|
||||
Todo
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{tasks.filter(t => t.status === 'Todo').map(task => (
|
||||
<Card key={task.id} className="p-3">
|
||||
<h5 className="font-medium">{task.title}</h5>
|
||||
<p className="text-sm text-muted-foreground mt-1">Due: {task.dueDate}</p>
|
||||
<div className="mt-3 h-1.5 w-full bg-gray-100 rounded-full">
|
||||
<div
|
||||
className="h-full bg-blue-500 rounded-full"
|
||||
style={{ width: `${task.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* In Progress Column */}
|
||||
<Card className="p-4">
|
||||
<h4 className="font-medium mb-4 flex items-center">
|
||||
<Clock className="h-4 w-4 mr-2" />
|
||||
In Progress
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{tasks.filter(t => t.status === 'In Progress').map(task => (
|
||||
<Card key={task.id} className="p-3">
|
||||
<h5 className="font-medium">{task.title}</h5>
|
||||
<p className="text-sm text-muted-foreground mt-1">Due: {task.dueDate}</p>
|
||||
<div className="mt-3 h-1.5 w-full bg-gray-100 rounded-full">
|
||||
<div
|
||||
className="h-full bg-blue-500 rounded-full"
|
||||
style={{ width: `${task.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Done Column */}
|
||||
<Card className="p-4">
|
||||
<h4 className="font-medium mb-4 flex items-center">
|
||||
<CheckCircle2 className="h-4 w-4 mr-2" />
|
||||
Done
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{tasks.filter(t => t.status === 'Done').map(task => (
|
||||
<Card key={task.id} className="p-3">
|
||||
<h5 className="font-medium">{task.title}</h5>
|
||||
<p className="text-sm text-muted-foreground mt-1">Due: {task.dueDate}</p>
|
||||
<div className="mt-3 h-1.5 w-full bg-gray-100 rounded-full">
|
||||
<div
|
||||
className="h-full bg-blue-500 rounded-full"
|
||||
style={{ width: `${task.progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="calendar" className="space-y-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<h3 className="text-lg font-medium">Calendar</h3>
|
||||
<Button variant="outline">
|
||||
<Calendar className="mr-2 h-4 w-4" />
|
||||
Select Date
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4">
|
||||
{/* Task Details */}
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
<Card className="p-6">
|
||||
<div className="space-y-6">
|
||||
{/* Today's Schedule */}
|
||||
<div>
|
||||
<h4 className="font-medium mb-4">Today's Schedule</h4>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-14 text-sm text-muted-foreground">09:00 AM</div>
|
||||
<div className="flex-1">
|
||||
<Card className="p-3">
|
||||
<h5 className="font-medium">Team Standup</h5>
|
||||
<p className="text-sm text-muted-foreground">Daily team sync meeting</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-14 text-sm text-muted-foreground">02:00 PM</div>
|
||||
<div className="flex-1">
|
||||
<Card className="p-3">
|
||||
<h5 className="font-medium">Design Review</h5>
|
||||
<p className="text-sm text-muted-foreground">Review new landing page design</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-14 text-sm text-muted-foreground">04:30 PM</div>
|
||||
<div className="flex-1">
|
||||
<Card className="p-3">
|
||||
<h5 className="font-medium">Sprint Planning</h5>
|
||||
<p className="text-sm text-muted-foreground">Plan next sprint tasks</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg font-medium mb-4">Task Description</h3>
|
||||
<RichTextEditor
|
||||
className="min-h-[200px]"
|
||||
content="<p>Add your task description here...</p>"
|
||||
onChange={(content) => console.log(content)}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
{/* Upcoming Events */}
|
||||
<div>
|
||||
<h4 className="font-medium mb-4">Upcoming Events</h4>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-20 text-sm text-muted-foreground">Tomorrow</div>
|
||||
<div className="flex-1">
|
||||
<Card className="p-3">
|
||||
<h5 className="font-medium">Client Meeting</h5>
|
||||
<p className="text-sm text-muted-foreground">10:00 AM - Project update discussion</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-20 text-sm text-muted-foreground">Friday</div>
|
||||
<div className="flex-1">
|
||||
<Card className="p-3">
|
||||
<h5 className="font-medium">Team Building</h5>
|
||||
<p className="text-sm text-muted-foreground">02:00 PM - Virtual team activity</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Card className="p-6">
|
||||
<h3 className="text-lg font-medium mb-4">Attachments</h3>
|
||||
<FileUpload
|
||||
onUpload={(files) => console.log("Uploaded files:", files)}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
118
app/globals.css
118
app/globals.css
|
|
@ -3,70 +3,96 @@
|
|||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
html,
|
||||
body {
|
||||
@apply bg-background;
|
||||
}
|
||||
|
||||
:root {
|
||||
/* Adjust these to change the theme's color */
|
||||
--primary: 234 88% 74%;
|
||||
--primary-foreground: 0 0% 0%;
|
||||
|
||||
/* Adjust these to change the chart's colors */
|
||||
--chart-1: 208 87% 53%;
|
||||
--chart-2: 301 56% 56%;
|
||||
--chart-3: 99 55% 51%;
|
||||
--chart-4: 56 70% 54%;
|
||||
--chart-5: 0 60% 57%;
|
||||
|
||||
--background: 0 0% 100%;
|
||||
--background-hover: 0 0% 95%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
|
||||
--primary: 0 0% 9%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 45.1%;
|
||||
|
||||
--accent: 0 0% 96.1%;
|
||||
--accent-foreground: 0 0% 9%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 240 5.9% 10%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--ring: 0 0% 3.9%;
|
||||
|
||||
--radius: 0.3rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 249 11% 12%;
|
||||
--background-hover: 0 0% 13%;
|
||||
--background: 0 0% 0%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 240 10% 3.9%;
|
||||
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 240 10% 3.9%;
|
||||
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 0 0% 9%;
|
||||
|
||||
--secondary: 0 0% 14.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 240 3.7% 15.9%;
|
||||
--muted-foreground: 240 5% 64.9%;
|
||||
--accent: 240 3.7% 15.9%;
|
||||
|
||||
--muted: 0 0% 14.9%;
|
||||
--muted-foreground: 0 0% 63.9%;
|
||||
|
||||
--accent: 0 0% 14.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
}
|
||||
|
||||
* {
|
||||
@apply border-border;
|
||||
--border: 0 0% 14.9%;
|
||||
--input: 0 0% 14.9%;
|
||||
--ring: 0 0% 83.1%;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
/* Custom scrollbar for modern browsers */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
@apply bg-muted;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
@apply bg-muted-foreground/50 rounded-full;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
@apply bg-muted-foreground;
|
||||
}
|
||||
|
||||
/* Base styles */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
|
@ -80,9 +106,9 @@ body {
|
|||
|
||||
main {
|
||||
flex: 1 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.disable-transitions * {
|
||||
transition-property: background-color, color !important;
|
||||
transition-duration: 0s !important;
|
||||
transition-property: none !important;
|
||||
}
|
||||
|
|
|
|||
62
app/page.tsx
62
app/page.tsx
|
|
@ -1,6 +1,5 @@
|
|||
import { Footer } from '@/components/footer'
|
||||
import { Header } from '@/components/header'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
|
|
@ -8,67 +7,6 @@ export default function Home() {
|
|||
<main className="w-full min-h-screen bg-gray-50">
|
||||
<div className="max-w-6xl mx-auto px-6">
|
||||
<Header />
|
||||
|
||||
<div className="relative mt-20 mb-40">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center space-y-8 relative z-10">
|
||||
<h1 className="text-6xl font-bold tracking-tight">
|
||||
Think, plan, and track
|
||||
<span className="block text-gray-400 mt-2">all in one place</span>
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
|
||||
Efficiently manage your tasks and boost productivity.
|
||||
</p>
|
||||
<div>
|
||||
<Button size="lg" className="bg-blue-500 hover:bg-blue-600">
|
||||
Get free demo
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Decorative Elements */}
|
||||
<div className="absolute top-0 left-0 w-full h-full overflow-hidden">
|
||||
{/* Yellow Note */}
|
||||
<div className="absolute left-20 top-20 transform -rotate-6">
|
||||
<div className="bg-yellow-100 p-6 rounded shadow-lg w-48">
|
||||
<p className="text-sm text-gray-700">Take notes to keep track of crucial details, and accomplish more tasks with ease.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Task List */}
|
||||
<div className="absolute right-20 bottom-20">
|
||||
<div className="bg-white p-4 rounded-lg shadow-lg w-64">
|
||||
<h3 className="font-semibold mb-3">Today's tasks</h3>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-full bg-blue-100 rounded">
|
||||
<div className="h-full w-3/5 bg-blue-500 rounded"></div>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500">60%</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-full bg-blue-100 rounded">
|
||||
<div className="h-full w-1/3 bg-blue-500 rounded"></div>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500">33%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Integrations */}
|
||||
<div className="absolute right-40 top-20">
|
||||
<div className="bg-white p-4 rounded-lg shadow-lg">
|
||||
<p className="text-sm font-medium mb-2">100+ Integrations</p>
|
||||
<div className="flex gap-2">
|
||||
<div className="w-8 h-8 bg-red-100 rounded"></div>
|
||||
<div className="w-8 h-8 bg-green-100 rounded"></div>
|
||||
<div className="w-8 h-8 bg-blue-100 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue