diff --git a/bun.lockb b/bun.lockb index 2b98866..cf736c2 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 65334d7..5be8d3b 100644 --- a/package.json +++ b/package.json @@ -11,15 +11,19 @@ "dependencies": { "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-slot": "^1.1.0", "@tanstack/react-table": "^8.20.1", "@types/qs": "^6.9.15", "axios": "^1.7.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "date-fns": "^3.6.0", + "lucide-react": "^0.428.0", "next": "14.2.5", "qs": "^6.13.0", "react": "^18", + "react-day-picker": "9.0.8", "react-dom": "^18", "sass": "^1.77.8", "tailwind-merge": "^2.5.2", diff --git a/src/components/people/PersonBirthdayCell.tsx b/src/components/people/PersonBirthdayCell.tsx index 8537d0b..2b9da47 100644 --- a/src/components/people/PersonBirthdayCell.tsx +++ b/src/components/people/PersonBirthdayCell.tsx @@ -1,5 +1,8 @@ import { IPerson } from '@/types/person' -import React from 'react' +import React, { useState } from 'react' +import { DatePicker } from '../ui/datepicker' +import { updatePerson } from '@/handlers/api/people.handler'; +import { formatDate } from '@/helpers/date.helper'; interface IProps { person: IPerson @@ -8,13 +11,31 @@ interface IProps { export default function PersonBirthdayCell( { person }: IProps ) { + const [formData, setFormData] = useState(person); + const [loading, setLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState(null); + + const handleEdit = (date?: Date | null) => { + if (!date) return; + const formatedDate = formatDate(date.toString(), 'yyyy-MM-dd'); + setLoading(true); + return updatePerson(person.id, { + birthDate: formatedDate, + }) + .then(() => { + + }) + .catch(() => {}) + .finally(() => { + setLoading(false); + }); + } + + + return (
- {person.birthDate ? ( - {person.birthDate.toDateString()} - ) : ( - Unknown - )} +
) } diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx new file mode 100644 index 0000000..6c36f3f --- /dev/null +++ b/src/components/ui/calendar.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons" +import { DayPicker } from "react-day-picker" +import "react-day-picker/dist/style.css"; + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +export type CalendarProps = React.ComponentProps + +function Calendar({ + className, + classNames, + showOutsideDays = true, + ...props +}: CalendarProps) { + return ( + + ) +} +Calendar.displayName = "Calendar" + +export { Calendar } diff --git a/src/components/ui/datepicker.tsx b/src/components/ui/datepicker.tsx new file mode 100644 index 0000000..6ccd136 --- /dev/null +++ b/src/components/ui/datepicker.tsx @@ -0,0 +1,52 @@ +"use client" + +import * as React from "react" +import { format } from "date-fns" +import { Calendar as CalendarIcon } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { Calendar } from "@/components/ui/calendar" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" + +interface IProps { + date?: Date | null + onSelect?: (date?: Date | null) => any +} +export function DatePicker( + { date: _date, onSelect }: IProps +) { + const [date, setDate] = React.useState(_date || null) + + const handleSelect = (date?: Date) => { + setDate(date || null) + onSelect?.(date) + } + return ( + + + + + + + + + ) +} diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx new file mode 100644 index 0000000..d82e714 --- /dev/null +++ b/src/components/ui/popover.tsx @@ -0,0 +1,31 @@ +import * as React from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" + +import { cn } from "@/lib/utils" + +const Popover = PopoverPrimitive.Root + +const PopoverTrigger = PopoverPrimitive.Trigger + +const PopoverAnchor = PopoverPrimitive.Anchor + +const PopoverContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( + + + +)) +PopoverContent.displayName = PopoverPrimitive.Content.displayName + +export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } diff --git a/src/handlers/api/people.handler.ts b/src/handlers/api/people.handler.ts index b33b6cd..77744d6 100644 --- a/src/handlers/api/people.handler.ts +++ b/src/handlers/api/people.handler.ts @@ -12,6 +12,10 @@ export const listPeople = (): Promise => { }); } -export const updatePerson = (id: string, data: Partial) => { +export const updatePerson = (id: string, data: Partial<{ + name: string; + birthDate: string; + isHidden: boolean; +}>) => { return API.put(UPDATE_PERSON_PATH(id), data) } \ No newline at end of file diff --git a/src/helpers/date.helper.ts b/src/helpers/date.helper.ts new file mode 100644 index 0000000..0b2a138 --- /dev/null +++ b/src/helpers/date.helper.ts @@ -0,0 +1,9 @@ +import { format, parse } from "date-fns" + +export const formatDate = (date: string, outputFormat?: string): string => { + return format(date, outputFormat || "PPP") +} + +export const parseDate = (date: string, inputFormat: string): Date => { + return parse(date, inputFormat, new Date()); +} \ No newline at end of file diff --git a/src/helpers/person.helper.ts b/src/helpers/person.helper.ts index 9a89d7d..0bb4daf 100644 --- a/src/helpers/person.helper.ts +++ b/src/helpers/person.helper.ts @@ -1,11 +1,17 @@ import { PERSON_THUBNAIL_PATH } from "@/config/routes" import { IPerson } from "@/types/person" +import { parseDate } from "./date.helper" -export const cleanUpPerson = (person: IPerson): IPerson => { +interface IAPIPerson extends Omit { + updatedAt: string; + birthDate: string | null; +} + +export const cleanUpPerson = (person: IAPIPerson): IPerson => { return { ...person, thumbnailPath: PERSON_THUBNAIL_PATH(person.id), - birthDate: person.birthDate ? new Date(person.birthDate) : null, + birthDate: person.birthDate ? new Date(parseDate(person.birthDate, 'yyyy-MM-dd')) : null, updatedAt: new Date(person.updatedAt), } } \ No newline at end of file