diff --git a/bun.lockb b/bun.lockb index a4ffb25..cc7295d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/messages/en.json b/messages/en.json index 5eb56c5..e7227ff 100644 --- a/messages/en.json +++ b/messages/en.json @@ -87,7 +87,19 @@ "tableDescription": "A list of your shopping cart items.", "backToStorage": "Back to storage", "cartEmpty": "Your shopping cart is empty.", - "clearCart": "Empty shopping cart" + "clearCart": "Empty shopping cart", + "borrowNow": "Borrow now" + }, + "loanForm": { + "name": "Name", + "nameDescription": "Person lending the item(s).", + "email": "Email", + "emailExample": "name@example.com", + "phoneNumber": "Phone number", + "phoneNumberDescription": "Phone number for contact. Include country code if the number isn't Norwegian.", + "returnBy": "Return by", + "returnByDescription": "Select how long you would like to borrow the item for.", + "submit": "Submit" } } } diff --git a/messages/no.json b/messages/no.json index 3c91dcd..d307092 100644 --- a/messages/no.json +++ b/messages/no.json @@ -87,7 +87,19 @@ "tableDescription": "En liste over handlekurven din.", "backToStorage": "Tilbake til lageret", "cartEmpty": "Handlekurven din er tom.", - "clearCart": "Tøm handlekurven" + "clearCart": "Tøm handlekurven", + "borrowNow": "Lån nå" + }, + "loanForm": { + "name": "Navn", + "nameDescription": "Personen som låner gjenstanden(e).", + "email": "Epost", + "emailExample": "navn@example.com", + "phoneNumber": "Mobilnummer", + "phoneNumberDescription": "Mobilnummer for kontakt. Inkluder landskode hvis mobilnummeret er ikke norsk.", + "returnBy": "Lån fram til", + "returnByDescription": "Velg hvor lenge du ønsker å låne gjenstanden(e)", + "submit": "Send" } } } diff --git a/package.json b/package.json index c0b8a23..ba34f88 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,12 @@ "start": "next start" }, "dependencies": { + "@hookform/resolvers": "^3.9.0", "@libsql/client": "^0.6.2", "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-select": "^2.1.1", "@radix-ui/react-separator": "^1.1.0", @@ -31,6 +33,7 @@ "cmdk": "1.0.0", "country-flag-icons": "^1.5.12", "cva": "^1.0.0-beta.1", + "date-fns": "^4.1.0", "drizzle-orm": "^0.31.2", "lucide-react": "^0.429.0", "next": "^14.2.4", @@ -39,7 +42,9 @@ "next-themes": "^0.3.0", "nuqs": "^1.17.4", "react": "^18.3.1", + "react-day-picker": "8.10.1", "react-dom": "^18.3.1", + "react-hook-form": "^7.53.0", "reading-time": "^1.5.0", "server-only": "^0.0.1", "sharp": "^0.33.4", diff --git a/src/app/[locale]/(default)/storage/page.tsx b/src/app/[locale]/(default)/storage/page.tsx index 84feeac..1fecb8b 100644 --- a/src/app/[locale]/(default)/storage/page.tsx +++ b/src/app/[locale]/(default)/storage/page.tsx @@ -6,7 +6,6 @@ import { createSearchParamsCache, parseAsInteger } from 'nuqs/parsers'; import { PaginationCarousel } from '@/components/layout/PaginationCarousel'; import { ItemCard } from '@/components/storage/ItemCard'; import { Button } from '@/components/ui/Button'; -import { Combobox } from '@/components/ui/Combobox'; import { SearchBar } from '@/components/ui/SearchBar'; import { diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index c4d6b54..19e0a06 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -14,6 +14,7 @@ export default function StorageShoppingCartPage({ }) { unstable_setRequestLocale(locale); const t = useTranslations('storage.shoppingCart'); + const tLoanForm = useTranslations('storage.loanForm'); const tableMessages = { tableDescription: t('tableDescription'), @@ -24,6 +25,18 @@ export default function StorageShoppingCartPage({ cartEmpty: t('cartEmpty'), }; + const loanFormMessages = { + name: tLoanForm('name'), + nameDescription: tLoanForm('nameDescription'), + email: tLoanForm('email'), + emailExample: tLoanForm('emailExample'), + phoneNumber: tLoanForm('phoneNumber'), + phoneNumberDescription: tLoanForm('phoneNumberDescription'), + returnBy: tLoanForm('returnBy'), + returnByDescription: tLoanForm('returnByDescription'), + submit: tLoanForm('submit'), + }; + return ( <>

{t('title')}

@@ -37,7 +50,10 @@ export default function StorageShoppingCartPage({ - +
+

{t('borrowNow')}

+ +
); } diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index 492ff05..7cd77b0 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -19,11 +19,25 @@ import { z } from 'zod'; const formSchema = z.object({ name: z.string().min(1), email: z.string().email(), - phone: z.string(), + phone: z.string().min(1), returnBy: z.date().min(new Date()), }); -function LoanForm() { +type LoanFormParams = { + t: { + name: string; + nameDescription: string; + email: string; + emailExample: string; + phoneNumber: string; + phoneNumberDescription: string; + returnBy: string; + returnByDescription: string; + submit: string; + }; +}; + +function LoanForm({ t }: LoanFormParams) { const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { @@ -35,6 +49,7 @@ function LoanForm() { }); function onSubmit(values: z.infer) { + // TODO: Add new loan to database console.log(values); } @@ -47,11 +62,11 @@ function LoanForm() { name='name' render={({ field }) => ( - Username + {t.name} - + - Person lending the item(s). + {t.nameDescription} )} @@ -61,13 +76,10 @@ function LoanForm() { name='email' render={({ field }) => ( - Email + {t.email} - + - {/* - This is your public display name. - */} )} @@ -77,25 +89,23 @@ function LoanForm() { name='phone' render={({ field }) => ( - Phone number + {t.phoneNumber} - + - {/* - This is your public display name. - */} + {t.phoneNumberDescription} )} /> -
+
( - Username + {t.returnBy} - - This is your public display name. - + {t.returnByDescription} )} />
- - {/* ( - - Username - - - - - This is your public display name. - - - - )} - /> */} ); diff --git a/src/components/ui/Label.tsx b/src/components/ui/Label.tsx index 31bafe8..0fe725c 100644 --- a/src/components/ui/Label.tsx +++ b/src/components/ui/Label.tsx @@ -1,14 +1,14 @@ 'use client'; import * as LabelPrimitive from '@radix-ui/react-label'; -import { type VariantProps, cva } from 'class-variance-authority'; +import { type VariantProps, cva } from 'cva'; import * as React from 'react'; import { cx } from '@/lib/utils'; -const labelVariants = cva( - 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', -); +const labelVariants = cva({ + base: 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', +}); const Label = React.forwardRef< React.ElementRef,