diff --git a/.idea/git_toolbox_blame.xml b/.idea/git_toolbox_blame.xml new file mode 100644 index 0000000..7dc1249 --- /dev/null +++ b/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 4e90f88..c506578 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components.json b/components.json new file mode 100644 index 0000000..af7b002 --- /dev/null +++ b/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/styles/globals.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} \ No newline at end of file diff --git a/package.json b/package.json index 82ecf05..a22da4e 100644 --- a/package.json +++ b/package.json @@ -10,17 +10,21 @@ "format": "prettier --write ." }, "dependencies": { + "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toggle-group": "^1.0.4", "@tanstack/react-query": "^4.28.0", "async-mutex": "^0.5.0", "axios": "^1.3.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", - "lucide-react": "^0.377.0", + "lucide-react": "^0.427.0", "next": "13.2.4", + "next-themes": "^0.3.0", "react": "18.2.0", "react-dom": "18.2.0", - "tailwind-merge": "^2.3.0", + "tailwind-merge": "^2.5.0", + "tailwindcss-animate": "^1.0.7", "zod": "^3.21.4" }, "devDependencies": { diff --git a/src/components/auth-redirect/index.tsx b/src/components/auth-redirect/index.tsx index dd5f54a..280cb02 100644 --- a/src/components/auth-redirect/index.tsx +++ b/src/components/auth-redirect/index.tsx @@ -3,7 +3,7 @@ import { useEffect } from "react" import { useRouter } from "next/router" -import { Loader } from "../loader" +import { Loader } from "../ui/loader" import { useMeQuery } from "@/services" diff --git a/src/components/button/index.tsx b/src/components/button/index.tsx deleted file mode 100644 index 6088487..0000000 --- a/src/components/button/index.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import type { ComponentPropsWithoutRef, FC } from "react" - -import { cn } from "@/helpers" - -type Props = ComponentPropsWithoutRef<"button"> & { - variant?: "primary" | "outlined" | "icon" -} - -export const Button: FC = ({ - className, - variant = "primary", - ...rest -}) => { - return ( - + + + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + + + ) +} diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx new file mode 100644 index 0000000..30d1451 --- /dev/null +++ b/src/components/theme-provider.tsx @@ -0,0 +1,9 @@ +"use client" + +import { ThemeProvider as NextThemesProvider } from "next-themes" +import type { ThemeProviderProps } from "next-themes/dist/types" +import * as React from "react" + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children} +} diff --git a/src/components/todolist/index.tsx b/src/components/todolist/index.tsx index 5bf07bd..b90d1cf 100644 --- a/src/components/todolist/index.tsx +++ b/src/components/todolist/index.tsx @@ -1,19 +1,31 @@ -import type { ChangeEvent, FC, FormEvent } from "react" +import { + type ChangeEvent, + type FC, + type FormEvent, + useCallback, + useMemo, +} from "react" import { memo, useState } from "react" +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card" import { Plus, Trash } from "lucide-react" - import type { Task, Todolist as TodolistType, } from "../../services/todolist-api/todolists" -import { Button } from "../button" -import { Input } from "../input" +import { Button } from "../ui/button" +import { Input } from "../ui/input" -import { - ToggleGroup, - ToggleGroupItem, -} from "@/components/toggle-group/toggle-group" +import { Checkbox } from "@/components/ui/checkbox" +import { Skeleton } from "@/components/ui/skeleton" +import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group" import { TaskStatus, useCreateTaskMutation, @@ -31,33 +43,42 @@ type Filter = "all" | "active" | "completed" export const Todolist: FC = memo(({ todolist }) => { const { data: tasks, isLoading } = useGetTasksQuery(todolist.id) - const { mutate: putTask } = useUpdateTaskMutation() + const { mutate: updateTask } = useUpdateTaskMutation() const { mutate: deleteTask } = useDeleteTaskMutation() const { mutate: deleteTodolist } = useDeleteTodolistMutation() const { mutate: createTask } = useCreateTaskMutation() const [newTaskTitle, setNewTaskTitle] = useState("") const [filter, setFilter] = useState("all") - const handleChangeStatus = (todolistId: string, task: Task) => { - const newTask: Task = { - ...task, - status: - task.status === TaskStatus.DONE ? TaskStatus.OPEN : TaskStatus.DONE, - } + const handleChangeStatus = useCallback( + (todolistId: string, task: Task) => { + updateTask({ + todolistId, + id: task.id, + status: + task.status === TaskStatus.DONE ? TaskStatus.OPEN : TaskStatus.DONE, + }) + }, + [updateTask], + ) + + const handleDeleteTask = useCallback( + (todolistId: string, taskId: string) => { + deleteTask({ todolistId, taskId }) + }, + [deleteTask], + ) - putTask({ todolistId, task: newTask }) - } - const handleDeleteTask = (todolistId: string, taskId: string) => { - deleteTask({ todolistId, taskId }) - } const handleDeleteTodolist = (todolistId: string) => { deleteTodolist({ todolistId }) } + const handleAddTask = (e: FormEvent) => { e.preventDefault() createTask({ todolistId: todolist.id, title: newTaskTitle }) setNewTaskTitle("") } + const handleNewTaskTitleChange = (e: ChangeEvent) => { setNewTaskTitle(e.target.value) } @@ -66,7 +87,6 @@ export const Todolist: FC = memo(({ todolist }) => { setFilter(value as Filter) } - if (isLoading) return
loading...
const filteredTasks = tasks?.filter((task) => { switch (filter) { case "active": @@ -78,53 +98,57 @@ export const Todolist: FC = memo(({ todolist }) => { } }) + const renderTasks = useMemo(() => { + return filteredTasks?.map((task) => { + return ( +
  • + + +
  • + ) + }) + }, [filteredTasks, todolist.id, handleChangeStatus, handleDeleteTask]) + return ( -
    -
    -

    {todolist.title}

    - -
    -
    - - -
    - {filteredTasks?.map((task) => { - return ( -
    - - + + +
    + + -
    - ) - })} -
    + +
      {isLoading ? null : renderTasks}
    + +
    + = memo(({ todolist }) => { className={"w-full"} > - All + ALL - Active + TODO - Completed + DONE -
    - + + ) }) diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..1620e13 --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,56 @@ +import { Slot } from "@radix-ui/react-slot" +import { type VariantProps, cva } from "class-variance-authority" +import * as React from "react" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10 shrink-0", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + }, +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx new file mode 100644 index 0000000..afa13ec --- /dev/null +++ b/src/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

    +)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

    +)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

    +)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx new file mode 100644 index 0000000..ddbdd01 --- /dev/null +++ b/src/components/ui/checkbox.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { Check } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..769ff7a --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,198 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/src/components/ui/input/index.tsx b/src/components/ui/input/index.tsx new file mode 100644 index 0000000..96600ef --- /dev/null +++ b/src/components/ui/input/index.tsx @@ -0,0 +1,35 @@ +import { Label } from "@/components/ui/label" +import { cn } from "@/helpers" +import * as React from "react" +import { useId } from "react" + +export interface InputProps + extends React.InputHTMLAttributes { + label?: string +} + +const Input = React.forwardRef( + ({ className, type, label, id, ...props }, ref) => { + const generatedId = useId() + const idToUse = id || generatedId + + return ( +
    + {label && } + +
    + ) + }, +) +Input.displayName = "Input" + +export { Input } diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx new file mode 100644 index 0000000..683faa7 --- /dev/null +++ b/src/components/ui/label.tsx @@ -0,0 +1,24 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/src/components/loader/index.tsx b/src/components/ui/loader/index.tsx similarity index 100% rename from src/components/loader/index.tsx rename to src/components/ui/loader/index.tsx diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx new file mode 100644 index 0000000..01b8b6d --- /dev/null +++ b/src/components/ui/skeleton.tsx @@ -0,0 +1,15 @@ +import { cn } from "@/lib/utils" + +function Skeleton({ + className, + ...props +}: React.HTMLAttributes) { + return ( +
    + ) +} + +export { Skeleton } diff --git a/src/components/toggle-group/toggle-group.tsx b/src/components/ui/toggle-group.tsx similarity index 66% rename from src/components/toggle-group/toggle-group.tsx rename to src/components/ui/toggle-group.tsx index 2d1acc9..8bfe044 100644 --- a/src/components/toggle-group/toggle-group.tsx +++ b/src/components/ui/toggle-group.tsx @@ -1,34 +1,10 @@ -"use client" - -import * as React from "react" - import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" import type { VariantProps } from "class-variance-authority" -import { cva } from "class-variance-authority" +import * as React from "react" -import { cn } from "@/helpers" +import { toggleVariants } from "@/components/ui/toggle" +import { cn } from "@/lib/utils" -const toggleVariants = cva( - "inline-flex border border-sky-700 items-center justify-center rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-sky-700 data-[state=on]:text-white", - { - variants: { - variant: { - default: "bg-transparent", - outline: - "border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground", - }, - size: { - default: "h-9 px-3", - sm: "h-8 px-2", - lg: "h-10 px-3", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - }, -) const ToggleGroupContext = React.createContext< VariantProps >({ diff --git a/src/components/ui/toggle.tsx b/src/components/ui/toggle.tsx new file mode 100644 index 0000000..9ecac28 --- /dev/null +++ b/src/components/ui/toggle.tsx @@ -0,0 +1,43 @@ +import * as React from "react" +import * as TogglePrimitive from "@radix-ui/react-toggle" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const toggleVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground", + { + variants: { + variant: { + default: "bg-transparent", + outline: + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + }, + size: { + default: "h-10 px-3", + sm: "h-9 px-2.5", + lg: "h-11 px-5", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +const Toggle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, ...props }, ref) => ( + +)) + +Toggle.displayName = TogglePrimitive.Root.displayName + +export { Toggle, toggleVariants } diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..d084cca --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 20aa50d..d1dd042 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,9 +1,12 @@ import "../styles/globals.css" -import { QueryClientProvider, QueryClient } from "@tanstack/react-query" +import { QueryClient, QueryClientProvider } from "@tanstack/react-query" import type { AppType } from "next/dist/shared/lib/utils" -import { AuthRedirect } from "@/components" +import { AuthRedirect, Button } from "@/components" +import { ModeToggle } from "@/components/mode-toggle" +import { ThemeProvider } from "@/components/theme-provider" +import { useLogoutMutation } from "@/services" const queryClient = new QueryClient() @@ -11,10 +14,36 @@ const MyApp: AppType = ({ Component, pageProps }) => { return ( - + +
    + + ) } +function Header() { + const { mutate: logout } = useLogoutMutation() + const handleLogout = () => { + logout() + } + return ( +
    +

    Tasks

    +
    + + +
    +
    + ) +} + export default MyApp diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx new file mode 100644 index 0000000..ddb4eb0 --- /dev/null +++ b/src/pages/_document.tsx @@ -0,0 +1,13 @@ +import { Head, Html, Main, NextScript } from "next/document" + +export default function Document() { + return ( + + + +
    + + + + ) +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index d1a5542..59ae411 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,25 +1,17 @@ -import type { ChangeEvent, FormEvent } from "react" +import { type ChangeEvent, type FormEvent, useMemo } from "react" import { useState } from "react" import type { NextPage } from "next" import Head from "next/head" -import { Todolist, Button, FullscreenLoader, Input } from "@/components" -import { - useCreateTodolistMutation, - useLogoutMutation, - useTodolistsQuery, -} from "@/services" +import { Button, FullscreenLoader, Input, Todolist } from "@/components" +import { useCreateTodolistMutation, useTodolistsQuery } from "@/services" +import { Plus } from "lucide-react" const Home: NextPage = () => { const [newTodolistTitle, setNewTodolistTitle] = useState("") - const { mutate: logout } = useLogoutMutation() const { data: todolists, isLoading: isTodolistsLoading } = useTodolistsQuery() - const handleLogout = () => { - logout() - } - const { mutate: createTodolist } = useCreateTodolistMutation() const handleAddTodolist = (e: FormEvent) => { @@ -32,6 +24,12 @@ const Home: NextPage = () => { setNewTodolistTitle(e.target.value) } + const renderTodolists = useMemo(() => { + return todolists?.map((todolist) => { + return + }) + }, [todolists]) + if (isTodolistsLoading) return return ( @@ -41,26 +39,19 @@ const Home: NextPage = () => { -
    -

    Todolist

    - -
    - - + +
    -
    - {todolists?.map((todolist) => { - return - })} -
    +
    {renderTodolists}
    ) diff --git a/src/pages/login.tsx b/src/pages/login.tsx index 5f8c330..d95c73d 100644 --- a/src/pages/login.tsx +++ b/src/pages/login.tsx @@ -4,6 +4,7 @@ import React, { useState } from "react" import type { NextPage } from "next" import { Button, Input } from "@/components" +import { Label } from "@/components/ui/label" import { useLoginMutation } from "@/services" const Login: NextPage = () => { @@ -34,30 +35,30 @@ const Login: NextPage = () => { } return ( -
    +
    - + - + - diff --git a/src/services/todolist-api/todolists/todolists.api.ts b/src/services/todolist-api/todolists/todolists.api.ts index 2010988..613603e 100644 --- a/src/services/todolist-api/todolists/todolists.api.ts +++ b/src/services/todolist-api/todolists/todolists.api.ts @@ -26,7 +26,7 @@ export const TodolistAPI = { }, ) - return handleError(res.data) + return res.data }, async deleteTodolist({ todolistId }: { todolistId: string }) { @@ -60,8 +60,11 @@ export const TodolistAPI = { return res.data }, - async updateTask({ todolistId, task }: { todolistId: string; task: Task }) { - const { id, ...rest } = task + async updateTask({ + id, + todolistId, + ...rest + }: Partial & Required> & { todolistId: string }) { const res = await todolistApiInstance.patch( `/todolists/${todolistId}/tasks/${id}`, rest, diff --git a/src/services/todolist-api/todolists/todolists.hooks.ts b/src/services/todolist-api/todolists/todolists.hooks.ts index 91637cc..7f70fef 100644 --- a/src/services/todolist-api/todolists/todolists.hooks.ts +++ b/src/services/todolist-api/todolists/todolists.hooks.ts @@ -17,9 +17,8 @@ export const useCreateTodolistMutation = () => { return useMutation({ mutationFn: TodolistAPI.createTodolist, - //todo: add onMutate - onSuccess: async () => { - await queryClient.invalidateQueries([QUERY_KEYS.TODOLISTS]) + onSuccess: () => { + queryClient.invalidateQueries([QUERY_KEYS.TODOLISTS]) }, }) } diff --git a/src/styles/globals.css b/src/styles/globals.css index 831c996..e8e4f13 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,48 +1,72 @@ @tailwind base; @tailwind components; @tailwind utilities; -.loader { - width: 48px; - height: 48px; - border: 3px dotted #000; - border-style: solid solid dotted dotted; - border-radius: 50%; - display: inline-block; - position: relative; - box-sizing: border-box; - animation: rotation 2s linear infinite; -} -.loader::after { - content: ""; - box-sizing: border-box; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - margin: auto; - border: 3px dotted #ff3d00; - border-style: solid solid dotted; - width: 24px; - height: 24px; - border-radius: 50%; - animation: rotationBack 1s linear infinite; - transform-origin: center center; + +@layer base { + #__next{ + height: 100%; + } + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --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%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 10% 3.9%; + --radius: 0.5rem; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + } + + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.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%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } } -@keyframes rotation { - 0% { - transform: rotate(0deg); +@layer base { + * { + @apply border-border; } - 100% { - transform: rotate(360deg); + body { + @apply bg-background text-foreground; } -} -@keyframes rotationBack { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(-360deg); - } -} +} \ No newline at end of file diff --git a/tailwind.config.cjs b/tailwind.config.cjs deleted file mode 100644 index 54331dc..0000000 --- a/tailwind.config.cjs +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ["./src/**/*.{js,ts,jsx,tsx}"], - theme: { - extend: {}, - }, - plugins: [], -}; diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..84287e8 --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,80 @@ +import type { Config } from "tailwindcss" + +const config = { + darkMode: ["class"], + content: [ + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', + ], + prefix: "", + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, + }, + plugins: [require("tailwindcss-animate")], +} satisfies Config + +export default config \ No newline at end of file