mirror of
https://github.com/ahmadk953/tasko.git
synced 2025-04-30 18:59:37 +00:00
Added Basic Darkmode and Fixed Small Bugs
This commit is contained in:
parent
aacca3d141
commit
94fb5c7eb1
42 changed files with 593 additions and 72 deletions
|
@ -3,7 +3,7 @@ import { Button } from '@/components/ui/button';
|
|||
|
||||
export const Footer = () => {
|
||||
return (
|
||||
<div className='fixed bottom-0 w-full border-t bg-slate-100 p-4'>
|
||||
<div className='fixed bottom-0 w-full border-t bg-slate-100 p-4 dark:bg-slate-800'>
|
||||
<div className='mx-auto flex w-full items-center justify-between md:max-w-screen-2xl'>
|
||||
<Logo />
|
||||
<div className='flex w-full items-center justify-between space-x-4 md:block md:w-auto'>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { auth } from '@clerk/nextjs/server';
|
|||
|
||||
import { Logo } from '@/components/logo';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ModeToggle } from '@/components/ui/mode-toggle';
|
||||
|
||||
export const Navbar = async () => {
|
||||
const { userId } = await auth();
|
||||
|
@ -10,7 +11,7 @@ export const Navbar = async () => {
|
|||
let isSignedIn = !!userId;
|
||||
|
||||
return (
|
||||
<div className='fixed top-0 flex h-14 w-full items-center border-b bg-white px-4 shadow-sm'>
|
||||
<nav className='fixed top-0 z-50 flex h-14 w-full items-center border-b bg-white px-4 shadow-sm dark:bg-black'>
|
||||
<div className='mx-auto flex w-full items-center justify-between md:max-w-screen-2xl'>
|
||||
<Logo />
|
||||
<div className='ml-0 flex w-full flex-auto items-center space-x-1 md:ml-6 md:block md:w-auto md:space-x-4'>
|
||||
|
@ -30,16 +31,18 @@ export const Navbar = async () => {
|
|||
<Button size='sm' asChild>
|
||||
<Link href='/sign-up'>Get Tasko for Free</Link>
|
||||
</Button>
|
||||
<ModeToggle />
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className='flex w-full justify-between space-x-4 md:block md:w-auto'>
|
||||
<Button size='sm' variant='outline' asChild>
|
||||
<Link href='/select-org'>Dashboard</Link>
|
||||
</Button>
|
||||
<ModeToggle />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,7 +5,9 @@ import Link from 'next/link';
|
|||
const BlogPage = () => {
|
||||
return (
|
||||
<div className='ml-4 mr-4 flex flex-col items-center space-y-10'>
|
||||
<h1 className='text-4xl font-semibold text-neutral-700'>Blog</h1>
|
||||
<h1 className='text-4xl font-semibold text-neutral-800 dark:text-neutral-100'>
|
||||
Blog
|
||||
</h1>
|
||||
<div className='grid grid-cols-2 gap-20 md:grid-cols-3 lg:grid-cols-4'>
|
||||
{allBlogPosts.map((post) => (
|
||||
<div className='space-y-4 text-center' key={post._meta.path}>
|
||||
|
@ -17,10 +19,12 @@ const BlogPage = () => {
|
|||
alt='post cover image'
|
||||
className='aspect-video w-full rounded-md object-cover'
|
||||
/>
|
||||
<h2 className='text-lg font-semibold text-neutral-700'>
|
||||
<h2 className='text-lg font-semibold text-neutral-800 dark:text-neutral-100'>
|
||||
{post.title}
|
||||
</h2>
|
||||
<p className='text-sm text-neutral-500'>{post.summary}</p>
|
||||
<p className='text-sm text-neutral-700 dark:text-neutral-200'>
|
||||
{post.summary}
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
@ -3,9 +3,11 @@ import { Navbar } from './_components/navbar';
|
|||
|
||||
const MarketingLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<div className='h-full bg-slate-100'>
|
||||
<div className='h-full bg-slate-100 dark:bg-slate-800'>
|
||||
<Navbar />
|
||||
<main className='bg-slate-100 pb-20 pt-20'>{children}</main>
|
||||
<main className='bg-slate-100 pb-20 pt-20 dark:bg-slate-800'>
|
||||
{children}
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ const MarketingPage = () => {
|
|||
<Medal className='mr-2 h-6 w-6' />
|
||||
No 1 task management app
|
||||
</div>
|
||||
<h1 className='mb-6 text-center text-neutral-800 ~/md:~text-3xl/6xl'>
|
||||
<h1 className='mb-6 text-center text-neutral-800 ~/md:~text-3xl/6xl dark:text-neutral-100'>
|
||||
Tasko helps teams move
|
||||
</h1>
|
||||
<div className='w-fit rounded-md bg-gradient-to-r from-fuchsia-600 to-pink-600 p-2 px-4 pb-4 text-white ~/md:~text-3xl/6xl'>
|
||||
|
|
|
@ -6,10 +6,11 @@ import { Button } from '@/components/ui/button';
|
|||
import { FormPopover } from '@/components/form/form-popover';
|
||||
|
||||
import { MobileSidebar } from './mobile-sidebar';
|
||||
import { ModeToggle } from '@/components/ui/mode-toggle';
|
||||
|
||||
export const Navbar = () => {
|
||||
return (
|
||||
<nav className='fixed top-0 z-50 flex h-14 w-full items-center border-b bg-white px-4 shadow-sm'>
|
||||
<nav className='fixed top-0 z-50 flex h-14 w-full items-center border-b bg-white px-4 shadow-sm dark:bg-black'>
|
||||
<MobileSidebar />
|
||||
<div className='flex items-center gap-x-4'>
|
||||
<div className='hidden md:flex'>
|
||||
|
@ -60,6 +61,7 @@ export const Navbar = () => {
|
|||
},
|
||||
}}
|
||||
/>
|
||||
<ModeToggle />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
|
|
|
@ -68,8 +68,10 @@ export const NavItem = ({
|
|||
<AccordionTrigger
|
||||
onClick={() => onExpand(organization.id)}
|
||||
className={cn(
|
||||
'flex items-center gap-x-2 rounded-md p-1.5 text-start text-neutral-700 no-underline transition hover:bg-neutral-500/10 hover:no-underline',
|
||||
isActive && !isExpanded && 'bg-sky-500/10 text-sky-700'
|
||||
'flex items-center gap-x-2 rounded-md p-1.5 text-start text-neutral-700 no-underline transition hover:bg-neutral-500/10 hover:no-underline dark:text-neutral-200 dark:hover:bg-neutral-200/10',
|
||||
isActive &&
|
||||
!isExpanded &&
|
||||
'bg-sky-500/10 text-sky-700 dark:bg-sky-300/10 dark:text-sky-600'
|
||||
)}
|
||||
>
|
||||
<div className='flex items-center gap-x-2'>
|
||||
|
@ -84,7 +86,7 @@ export const NavItem = ({
|
|||
<span className='text-sm font-medium'>{organization.name}</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className='pt-1 text-neutral-700'>
|
||||
<AccordionContent className='pt-1 text-neutral-700 dark:text-neutral-200'>
|
||||
{routes.map((route) => (
|
||||
<Button
|
||||
key={route.href}
|
||||
|
@ -92,7 +94,8 @@ export const NavItem = ({
|
|||
onClick={() => onClick(route.href)}
|
||||
className={cn(
|
||||
'mb-1 w-full justify-start pl-10 font-normal',
|
||||
pathname === route.href && 'bg-sky-500/10 text-sky-700'
|
||||
pathname === route.href &&
|
||||
'bg-sky-500/10 text-sky-700 dark:bg-sky-300/10 dark:text-sky-600'
|
||||
)}
|
||||
variant='ghost'
|
||||
>
|
||||
|
|
|
@ -9,7 +9,7 @@ interface BoardNavbarProps {
|
|||
|
||||
export const BoardNavbar = ({ data }: BoardNavbarProps) => {
|
||||
return (
|
||||
<div className='fixed top-14 z-[40] flex h-14 w-full items-center gap-x-4 bg-black/50 px-6 text-white'>
|
||||
<div className='fixed top-14 z-[40] flex h-14 w-full items-center gap-x-4 bg-black/50 px-6 text-white dark:text-neutral-200'>
|
||||
<BoardTitleForm data={data} />
|
||||
<div className='ml-auto'>
|
||||
<BoardOptions id={data.id} />
|
||||
|
|
|
@ -54,12 +54,12 @@ export const BoardOptions = ({ id }: BoardOptionsProps) => {
|
|||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className='px-0 pb-3 pt-3' side='bottom' align='start'>
|
||||
<div className='pb-4 text-center text-sm font-medium text-neutral-600'>
|
||||
<div className='pb-4 text-center text-sm font-medium text-neutral-600 dark:text-neutral-200'>
|
||||
Board Actions
|
||||
</div>
|
||||
<PopoverClose asChild>
|
||||
<Button
|
||||
className='absolute right-2 top-2 h-auto w-auto p-2 text-neutral-600'
|
||||
className='absolute right-2 top-2 h-auto w-auto p-2 text-neutral-600 dark:text-neutral-200'
|
||||
variant='ghost'
|
||||
>
|
||||
<X className='h-4 w-4' />
|
||||
|
@ -69,7 +69,7 @@ export const BoardOptions = ({ id }: BoardOptionsProps) => {
|
|||
variant='ghost'
|
||||
onClick={onCopy}
|
||||
disabled={isLoadingCopy}
|
||||
className='h-auto w-full justify-start rounded-none p-2 px-5 text-sm font-normal text-neutral-600'
|
||||
className='h-auto w-full justify-start rounded-none p-2 px-5 text-sm font-normal text-neutral-600 dark:text-neutral-200'
|
||||
>
|
||||
Copy this Board
|
||||
</Button>
|
||||
|
@ -78,7 +78,7 @@ export const BoardOptions = ({ id }: BoardOptionsProps) => {
|
|||
variant='ghost'
|
||||
onClick={onDelete}
|
||||
disabled={isLoadingDelete}
|
||||
className='h-auto w-full justify-start rounded-none p-2 px-5 text-sm font-normal text-destructive hover:text-destructive'
|
||||
className='h-auto w-full justify-start rounded-none p-2 px-5 text-sm font-normal text-destructive hover:text-destructive dark:text-red-500 dark:hover:text-red-500'
|
||||
>
|
||||
Delete this Board
|
||||
</Button>
|
||||
|
|
|
@ -43,7 +43,7 @@ export const BoardUpdateImage = ({ boardId }: BoardUpdateImageProps) => {
|
|||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant='ghost'
|
||||
className='h-auto w-full justify-start p-2 px-5 text-sm font-normal text-neutral-600'
|
||||
className='h-auto w-full justify-start p-2 px-5 text-sm font-normal text-neutral-600 dark:text-neutral-200'
|
||||
>
|
||||
Change Background Image
|
||||
</Button>
|
||||
|
@ -51,7 +51,7 @@ export const BoardUpdateImage = ({ boardId }: BoardUpdateImageProps) => {
|
|||
<PopoverContent className='w-80 pt-3' side='left' align='start'>
|
||||
<PopoverClose asChild>
|
||||
<Button
|
||||
className='absolute right-2 top-2 h-auto w-auto p-2 text-neutral-600'
|
||||
className='absolute right-2 top-2 h-auto w-auto p-2 text-neutral-600 dark:text-neutral-200'
|
||||
variant='ghost'
|
||||
>
|
||||
<X className='h-4 w-4' />
|
||||
|
@ -59,10 +59,10 @@ export const BoardUpdateImage = ({ boardId }: BoardUpdateImageProps) => {
|
|||
</PopoverClose>
|
||||
<form action={onSubmit} className='space-y-4'>
|
||||
<div className='space-y-4'>
|
||||
<p className='text-center text-xs font-medium italic text-neutral-700'>
|
||||
<p className='text-center text-xs font-medium italic text-neutral-700 dark:text-neutral-100'>
|
||||
Images Provided by{' '}
|
||||
<Link
|
||||
className='text-sky-900 underline'
|
||||
className='text-sky-900 underline dark:text-sky-600'
|
||||
href='https://unsplash.com/'
|
||||
>
|
||||
Unsplash
|
||||
|
|
|
@ -24,17 +24,17 @@ export const CardItem = ({ index, data }: CardItemProps) => {
|
|||
ref={provided.innerRef}
|
||||
role='button'
|
||||
onClick={() => cardModal.onOpen(data.id)}
|
||||
className='space-y-2 truncate rounded-md border-2 border-transparent bg-white px-3 py-2 text-sm shadow-sm hover:border-black'
|
||||
className='space-y-2 truncate rounded-md border-2 border-transparent bg-white px-3 py-2 text-sm shadow-sm hover:border-black dark:bg-black dark:hover:border-white/50'
|
||||
>
|
||||
{data.title}
|
||||
{data?.dueDate && (
|
||||
<div className='flex w-fit rounded-md border-2 border-transparent bg-slate-100 px-0.5 pb-0.5 pt-0.5 text-sm'>
|
||||
<div className='flex w-fit rounded-md border-2 border-transparent bg-slate-100 px-0.5 pb-0.5 pt-0.5 text-sm dark:bg-slate-800'>
|
||||
<Calendar className='ml-0.5 mr-0.5 h-4 w-4' />
|
||||
Due: {format(data.dueDate, 'PP')}
|
||||
</div>
|
||||
)}
|
||||
{data?.startedAt && (
|
||||
<div className='flex w-fit rounded-md border-2 border-transparent bg-slate-100 px-0.5 pb-0.5 pt-0.5 text-sm'>
|
||||
<div className='flex w-fit rounded-md border-2 border-transparent bg-slate-100 px-0.5 pb-0.5 pt-0.5 text-sm dark:bg-slate-800'>
|
||||
<Calendar className='ml-0.5 mr-0.5 h-4 w-4' />
|
||||
Started: {format(data.startedAt, 'PP')}
|
||||
</div>
|
||||
|
|
|
@ -67,7 +67,7 @@ export const ListForm = () => {
|
|||
<form
|
||||
action={onSubmit}
|
||||
ref={formRef}
|
||||
className='w-full space-y-4 rounded-md bg-white p-3 shadow-md'
|
||||
className='w-full space-y-4 rounded-md bg-white p-3 shadow-md dark:bg-black'
|
||||
>
|
||||
<FormInput
|
||||
ref={inputRef}
|
||||
|
@ -92,7 +92,7 @@ export const ListForm = () => {
|
|||
<ListWrapper>
|
||||
<button
|
||||
onClick={enableEditing}
|
||||
className='flex w-full items-center rounded-md bg-white/80 p-3 text-sm font-medium transition hover:bg-white/50'
|
||||
className='flex w-full items-center rounded-md bg-white/80 p-3 text-sm font-medium transition hover:bg-white/50 dark:bg-white/10 dark:hover:bg-white/5'
|
||||
>
|
||||
<Plus className='mr-2 h-4 w-4' />
|
||||
Add a list
|
||||
|
|
|
@ -41,7 +41,7 @@ export const ListItem = ({ index, data }: ListItemProps) => {
|
|||
>
|
||||
<div
|
||||
{...provided.dragHandleProps}
|
||||
className='w-full rounded-md bg-[#f1f2f4] pb-2 shadow-md'
|
||||
className='w-full rounded-md bg-[#f1f2f4] pb-2 shadow-md dark:bg-[#1f1f1f]'
|
||||
>
|
||||
<ListHeader onAddCard={enableEditing} data={data} />
|
||||
<Droppable droppableId={data.id} type='card'>
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
import { auth } from '@clerk/nextjs/server';
|
||||
import { notFound, redirect } from 'next/navigation';
|
||||
import {
|
||||
LiveblocksProvider,
|
||||
RoomProvider,
|
||||
ClientSideSuspense,
|
||||
} from '@liveblocks/react/suspense';
|
||||
|
||||
import { db } from '@/lib/db';
|
||||
import { BoardNavbar } from './_components/board-navbar';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { BoardLiveblocks } from './_components/board-liveblocks';
|
||||
|
||||
export async function generateMetadata(props: {
|
||||
|
|
|
@ -32,7 +32,7 @@ export const BoardList = async () => {
|
|||
|
||||
return (
|
||||
<div className='space-y-4'>
|
||||
<div className='flex items-center text-lg font-semibold text-neutral-700'>
|
||||
<div className='flex items-center text-lg font-semibold text-neutral-700 dark:text-neutral-200'>
|
||||
<User2 className='mr-2 h-6 w-6' />
|
||||
Your boards
|
||||
</div>
|
||||
|
|
|
@ -64,14 +64,14 @@ const ActivityPage = async ({
|
|||
|
||||
export default ActivityPage;
|
||||
|
||||
const ActivityListSkeleton = () => {
|
||||
function ActivityListSkeleton() {
|
||||
return (
|
||||
<ol className='mt-4 space-y-4'>
|
||||
<div className='mt-4 space-y-4'>
|
||||
<Skeleton className='h-14 w-[80%]' />
|
||||
<Skeleton className='h-14 w-[50%]' />
|
||||
<Skeleton className='h-14 w-[70%]' />
|
||||
<Skeleton className='h-14 w-[80%]' />
|
||||
<Skeleton className='h-14 w-[75%]' />
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
'use client';
|
||||
|
||||
import { Toaster } from 'sonner';
|
||||
import { ClerkProvider } from '@clerk/nextjs';
|
||||
import { dark } from '@clerk/themes';
|
||||
import { useTheme } from 'next-themes';
|
||||
|
||||
import { ModalProvider } from '@/components/providers/modal-provider';
|
||||
import { QueryProvider } from '@/components/providers/query-provider';
|
||||
|
||||
const PlatformLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
return (
|
||||
<ClerkProvider afterSignOutUrl='/'>
|
||||
<ClerkProvider
|
||||
afterSignOutUrl='/'
|
||||
appearance={{
|
||||
baseTheme: theme === 'dark' ? dark : undefined,
|
||||
}}
|
||||
>
|
||||
<QueryProvider>
|
||||
<Toaster />
|
||||
<Toaster theme='system' />
|
||||
<ModalProvider />
|
||||
{children}
|
||||
</QueryProvider>
|
||||
|
|
|
@ -5,6 +5,7 @@ import type { Metadata } from 'next';
|
|||
|
||||
import './globals.css';
|
||||
import { siteConfig } from '@/config/site';
|
||||
import { ThemeProvider } from '@/components/theme-provider';
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] });
|
||||
|
||||
|
@ -28,10 +29,17 @@ export default function RootLayout({
|
|||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang='en'>
|
||||
<html lang='en' suppressHydrationWarning>
|
||||
<body className={inter.className}>
|
||||
<SpeedInsights />
|
||||
{children}
|
||||
<ThemeProvider
|
||||
attribute='class'
|
||||
defaultTheme='system'
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
<Analytics />
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue