From 0395cf2cf36cd16b608e91c0abcc3f74ccf580b0 Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Sun, 27 Oct 2024 13:42:30 +0100 Subject: [PATCH 01/12] chore: ran next 15 codemod --- bun.lockb | Bin 223963 -> 225484 bytes package.json | 18 +++++++----- src/app/[locale]/(default)/about/page.tsx | 20 ++++++++------ src/app/[locale]/(default)/events/page.tsx | 20 ++++++++------ src/app/[locale]/(default)/layout.tsx | 13 +++++---- .../[locale]/(default)/news/(main)/layout.tsx | 14 ++++++---- .../[locale]/(default)/news/(main)/page.tsx | 26 ++++++++++-------- .../(default)/news/[article]/page.tsx | 15 +++++----- src/app/[locale]/(default)/page.tsx | 10 ++++--- .../(default)/storage/(main)/layout.tsx | 15 ++++++---- .../(default)/storage/(main)/page.tsx | 25 ++++++++++------- .../storage/shopping-cart/layout.tsx | 14 ++++++---- .../(default)/storage/shopping-cart/page.tsx | 11 +++++--- src/app/[locale]/layout.tsx | 23 ++++++++++------ src/lib/api/server.ts | 4 +-- src/server/auth/user.ts | 7 +++-- 16 files changed, 141 insertions(+), 94 deletions(-) diff --git a/bun.lockb b/bun.lockb index 68cb1666a5b8cb1bbfc4f24284c67e21dc64b84a..74bddeac182145697a0cada4f09d62078b817f67 100755 GIT binary patch delta 46925 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

TS7j}$-LT_wEmFvR zJ%0x4y`0aqwwxu8px%!^znc~PTCA1$NWkn_?89>S>k2Gr^cjS^c0E(}t8ZZ;``&&w zb6$b^na^SER-p9DbJ%F;)_3PfBl_z`3-i6ZnYR<`DSpC(g>D;JzRO^D3D*eBawXs1 z{j!{5YTvnA59FV`DV-3+5=p={d|F7Vax#3&R#w6r-CM#RwaWmYLLvQONV zW};KYW4UjavJGodkDO)f7Ul7FnKWd^f8M#|y}6n6q?fn^8sth-?B~b(EDzg$JTI0n z9W%&fPV11i02buad-KzN&GmbY6V0d{&N4Zxp2;ysewn?tYW23i>tnd(Y$VcJS6wa* z4CfX(y>^$a%n+;LF@`2uhdtcf)B2cR%h@MNn+gl^ zo%y?WE?vHNkJVdDl4Fjlp0=&`fcMwOEL_goe}$TDmMt1q!5=H1`ctmn;@EPQ2@Cft zvW4LNxb}eQIg|AkkK~vWuQO|oT-gne4JaP@yquk-w5BVhkQ7qucRex-dAi1Qn;Uz z`yqa>&)TMC6Yq*C@HnNbs>Hq%W1i)*$5a}Jwovc7w?Dlrcg~IsecGzane7JTUJn*k zVX=JO=mAd+>t4`Xl-PG-?(LVeBud*$@l?6atj+zzqx!TZ_MMn^(sFhHX{{H^X|Ijz z*T!Xj{tBUh_s)PmNpbitep2)XUf4fd;#^YZ8+(IRvOI}8gRJ(a%^^Y6}9R%sJT`{ScC zPq#|jmG?ke%-iDEqehrH3>N2b6DJQmZnKT`K-xdK2#%e>W^KYn?~l3XZc9 zRxEup-^6OsPH7p^B>NnH7@UKXN~5uh@xlr=B!S6% z-8Q`rsMn5nJEW}h>0TR|0Ll|^|`=)0w@Y^hgL5M zU#%cn0px><u zC^AWeGvpQIT9s55q!#NIr6wkqH~?b;SkmhjCF>bFfW`H};%LfrQ}T0hDFw+*_t?bL zu>Hv5gxh6s9jf%p@s} z!(508y+cfF+g}`JTFNvX!~{82YP#DS;JLRzz1Gto9AgrgUU!K}dHaE5OuAfN;5H%1 zy-A5lsX4j@Ii=~Dd5|#IP0r6P$jnJC0_~gtW;BJG8U@_$10FDVoJn=M{c$Eu;LRS1 zZ<$o4KRC|BKi%O3lQOyh+jPB4OwvfAoFIK{Aa}_li3(3&a2!RM4w5A2^rFkaebWf5 zIHx~5!6XY2P@cXvh1p}e>KUNlOP&EEtn4I{45Qif$tRgq*g^h?Gqjuz+_|a<3JdHK-`lrT7FSi!j`P(!iWzW@4vcF`aQEldv@G3<3Cw0R`X; s#b8swJY8OqN!1Y8^8x2%m_i0%&V>{*Za^B8M`2nSAcqZr&M==00A2o<82|tP delta 45441 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 RrR@UQ%&jcbXI3yy007%f)7bz3 diff --git a/package.json b/package.json index 43e37e9..51c3098 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "prepare": "if [ \"$NODE_ENV\" != \"production\" ]; then lefthook install; fi", - "dev": "next dev", + "dev": "next dev --turbopack", "lint": "biome check --write", "prebuild": "next telemetry disable", "build": "next build", @@ -43,14 +43,14 @@ "drizzle-orm": "^0.33.0", "lucia": "^3.2.0", "lucide-react": "^0.396.0", - "next": "^14.2.10", + "next": "15.0.1", "next-intl": "^3.18.1", "next-themes": "^0.3.0", "nuqs": "^1.17.4", "postgres": "^3.4.4", - "react": "^18.3.1", + "react": "19.0.0-rc-69d4b800-20241021", "react-day-picker": "8.10.1", - "react-dom": "^18.3.1", + "react-dom": "19.0.0-rc-69d4b800-20241021", "react-hook-form": "^7.53.0", "reading-time": "^1.5.0", "sharp": "^0.33.4", @@ -62,8 +62,8 @@ "@biomejs/biome": "^1.9.1", "@fluid-tailwind/tailwind-merge": "^0.0.2", "@types/node": "^20.14.8", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", "autoprefixer": "^10.4.20", "client-only": "^0.0.1", "drizzle-kit": "^0.24.1", @@ -78,5 +78,9 @@ "tailwindcss-radix": "^3.0.5", "typescript": "^5.5.0" }, - "packageManager": "bun@1.1.12" + "packageManager": "bun@1.1.12", + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" + } } diff --git a/src/app/[locale]/(default)/about/page.tsx b/src/app/[locale]/(default)/about/page.tsx index a16200f..66806b9 100644 --- a/src/app/[locale]/(default)/about/page.tsx +++ b/src/app/[locale]/(default)/about/page.tsx @@ -1,10 +1,12 @@ import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; -export async function generateMetadata({ - params: { locale }, -}: { - params: { locale: string }; +export async function generateMetadata(props: { + params: Promise<{ locale: string }>; }) { + const params = await props.params; + + const { locale } = params; + const t = await getTranslations({ locale, namespace: 'layout' }); return { @@ -12,11 +14,13 @@ export async function generateMetadata({ }; } -export default function AboutPage({ - params: { locale }, -}: { - params: { locale: string }; +export default async function AboutPage(props: { + params: Promise<{ locale: string }>; }) { + const params = await props.params; + + const { locale } = params; + unstable_setRequestLocale(locale); return

this should be about page
; } diff --git a/src/app/[locale]/(default)/events/page.tsx b/src/app/[locale]/(default)/events/page.tsx index 1477014..17ff759 100644 --- a/src/app/[locale]/(default)/events/page.tsx +++ b/src/app/[locale]/(default)/events/page.tsx @@ -1,10 +1,12 @@ import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; -export async function generateMetadata({ - params: { locale }, -}: { - params: { locale: string }; +export async function generateMetadata(props: { + params: Promise<{ locale: string }>; }) { + const params = await props.params; + + const { locale } = params; + const t = await getTranslations({ locale, namespace: 'layout' }); return { @@ -12,11 +14,13 @@ export async function generateMetadata({ }; } -export default function EventsPage({ - params: { locale }, -}: { - params: { locale: string }; +export default async function EventsPage(props: { + params: Promise<{ locale: string }>; }) { + const params = await props.params; + + const { locale } = params; + unstable_setRequestLocale(locale); return
This should be events page
; } diff --git a/src/app/[locale]/(default)/layout.tsx b/src/app/[locale]/(default)/layout.tsx index c01ad96..e90b9f7 100644 --- a/src/app/[locale]/(default)/layout.tsx +++ b/src/app/[locale]/(default)/layout.tsx @@ -5,13 +5,16 @@ import { unstable_setRequestLocale } from 'next-intl/server'; type DefaultLayoutProps = { children: React.ReactNode; - params: { locale: string }; + params: Promise<{ locale: string }>; }; -export default function DefaultLayout({ - children, - params: { locale }, -}: DefaultLayoutProps) { +export default async function DefaultLayout(props: DefaultLayoutProps) { + const params = await props.params; + + const { locale } = params; + + const { children } = props; + unstable_setRequestLocale(locale); return ( <> diff --git a/src/app/[locale]/(default)/news/(main)/layout.tsx b/src/app/[locale]/(default)/news/(main)/layout.tsx index feebab9..bef72bc 100644 --- a/src/app/[locale]/(default)/news/(main)/layout.tsx +++ b/src/app/[locale]/(default)/news/(main)/layout.tsx @@ -1,6 +1,7 @@ import { SquarePenIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; +import { use } from 'react'; import { Link } from '@/lib/locale/navigation'; @@ -8,13 +9,16 @@ import { Button } from '@/components/ui/Button'; type NewsHeaderLayoutProps = { children: React.ReactNode; - params: { locale: string }; + params: Promise<{ locale: string }>; }; -export default function NewsHeaderLayout({ - children, - params: { locale }, -}: NewsHeaderLayoutProps) { +export default function NewsHeaderLayout(props: NewsHeaderLayoutProps) { + const params = use(props.params); + + const { locale } = params; + + const { children } = props; + unstable_setRequestLocale(locale); const t = useTranslations('news'); return ( diff --git a/src/app/[locale]/(default)/news/(main)/page.tsx b/src/app/[locale]/(default)/news/(main)/page.tsx index a7bfa8d..2dc84fc 100644 --- a/src/app/[locale]/(default)/news/(main)/page.tsx +++ b/src/app/[locale]/(default)/news/(main)/page.tsx @@ -2,7 +2,7 @@ import { articleMockData as articleData } from '@/mock-data/article'; import { useTranslations } from 'next-intl'; import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; import { createSearchParamsCache, parseAsInteger } from 'nuqs/server'; -import { Suspense } from 'react'; +import { Suspense, use } from 'react'; import { PaginationCarousel } from '@/components/composites/PaginationCarousel'; import { CardGrid } from '@/components/news/CardGrid'; @@ -10,11 +10,13 @@ import { ItemGrid } from '@/components/news/ItemGrid'; import { ItemGridSkeleton } from '@/components/news/ItemGridSkeleton'; import { Separator } from '@/components/ui/Separator'; -export async function generateMetadata({ - params: { locale }, -}: { - params: { locale: string }; +export async function generateMetadata(props: { + params: Promise<{ locale: string }>; }) { + const params = await props.params; + + const { locale } = params; + const t = await getTranslations({ locale, namespace: 'layout' }); return { @@ -22,13 +24,15 @@ export async function generateMetadata({ }; } -export default function NewsPage({ - params: { locale }, - searchParams, -}: { - params: { locale: string }; - searchParams: Record; +export default function NewsPage(props: { + params: Promise<{ locale: string }>; + searchParams: Promise>; }) { + const searchParams = use(props.searchParams); + const params = use(props.params); + + const { locale } = params; + unstable_setRequestLocale(locale); const t = useTranslations('ui'); const searchParamsCache = createSearchParamsCache({ diff --git a/src/app/[locale]/(default)/news/[article]/page.tsx b/src/app/[locale]/(default)/news/[article]/page.tsx index a9b96f3..2fa59ea 100644 --- a/src/app/[locale]/(default)/news/[article]/page.tsx +++ b/src/app/[locale]/(default)/news/[article]/page.tsx @@ -6,6 +6,7 @@ import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; import Image from 'next/image'; import { notFound } from 'next/navigation'; +import { use } from 'react'; import readingTime from 'reading-time'; import { AvatarIcon } from '@/components/profile/AvatarIcon'; @@ -17,11 +18,10 @@ import { Badge } from '@/components/ui/Badge'; // })); // } -export async function generateMetadata({ - params, -}: { - params: { article: string }; +export async function generateMetadata(props: { + params: Promise<{ article: string }>; }) { + const params = await props.params; const article = articleData.find( (article) => article.id === Number(params.article), ); @@ -31,11 +31,10 @@ export async function generateMetadata({ }; } -export default function ArticlePage({ - params, -}: { - params: { locale: string; article: string }; +export default function ArticlePage(props: { + params: Promise<{ locale: string; article: string }>; }) { + const params = use(props.params); unstable_setRequestLocale(params.locale); const t = useTranslations('news'); diff --git a/src/app/[locale]/(default)/page.tsx b/src/app/[locale]/(default)/page.tsx index af70a75..a015cbc 100644 --- a/src/app/[locale]/(default)/page.tsx +++ b/src/app/[locale]/(default)/page.tsx @@ -2,11 +2,13 @@ import { HelloWorld } from '@/components/home/HelloWorld'; import { api } from '@/lib/api/server'; import { unstable_setRequestLocale } from 'next-intl/server'; -export default async function HomePage({ - params: { locale }, -}: { - params: { locale: string }; +export default async function HomePage(props: { + params: Promise<{ locale: string }>; }) { + const params = await props.params; + + const { locale } = params; + unstable_setRequestLocale(locale); const hello = await api.test.helloWorld(); return ( diff --git a/src/app/[locale]/(default)/storage/(main)/layout.tsx b/src/app/[locale]/(default)/storage/(main)/layout.tsx index 4bddd7a..649fc2d 100644 --- a/src/app/[locale]/(default)/storage/(main)/layout.tsx +++ b/src/app/[locale]/(default)/storage/(main)/layout.tsx @@ -5,17 +5,20 @@ import { SelectorsSkeleton } from '@/components/storage/SelectorsSkeleton'; import { ShoppingCartLink } from '@/components/storage/ShoppingCartLink'; import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; -import { Suspense } from 'react'; +import { Suspense, use } from 'react'; type StorageLayoutProps = { children: React.ReactNode; - params: { locale: string }; + params: Promise<{ locale: string }>; }; -export default function StorageLayout({ - children, - params: { locale }, -}: StorageLayoutProps) { +export default function StorageLayout(props: StorageLayoutProps) { + const params = use(props.params); + + const { locale } = params; + + const { children } = props; + unstable_setRequestLocale(locale); const t = useTranslations('storage'); const tUi = useTranslations('ui'); diff --git a/src/app/[locale]/(default)/storage/(main)/page.tsx b/src/app/[locale]/(default)/storage/(main)/page.tsx index 9bbb49a..eedbae3 100644 --- a/src/app/[locale]/(default)/storage/(main)/page.tsx +++ b/src/app/[locale]/(default)/storage/(main)/page.tsx @@ -2,15 +2,18 @@ import { items } from '@/mock-data/items'; import { useTranslations } from 'next-intl'; import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; import { createSearchParamsCache, parseAsInteger } from 'nuqs/server'; +import { use } from 'react'; import { PaginationCarousel } from '@/components/composites/PaginationCarousel'; import { ItemCard } from '@/components/storage/ItemCard'; -export async function generateMetadata({ - params: { locale }, -}: { - params: { locale: string }; +export async function generateMetadata(props: { + params: Promise<{ locale: string }>; }) { + const params = await props.params; + + const { locale } = params; + const t = await getTranslations({ locale, namespace: 'layout' }); return { @@ -18,13 +21,15 @@ export async function generateMetadata({ }; } -export default function StoragePage({ - params: { locale }, - searchParams, -}: { - params: { locale: string }; - searchParams: Record; +export default function StoragePage(props: { + params: Promise<{ locale: string }>; + searchParams: Promise>; }) { + const searchParams = use(props.searchParams); + const params = use(props.params); + + const { locale } = params; + unstable_setRequestLocale(locale); const t = useTranslations('ui'); diff --git a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx index 8235cb2..c2075f2 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx @@ -3,16 +3,20 @@ import { Link } from '@/lib/locale/navigation'; import { ArrowLeftIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; +import { use } from 'react'; type ShoppingCartLayoutProps = { children: React.ReactNode; - params: { locale: string }; + params: Promise<{ locale: string }>; }; -export default function StorageLayout({ - children, - params: { locale }, -}: ShoppingCartLayoutProps) { +export default function StorageLayout(props: ShoppingCartLayoutProps) { + const params = use(props.params); + + const { locale } = params; + + const { children } = props; + unstable_setRequestLocale(locale); const t = useTranslations('storage.shoppingCart'); return ( diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index f72474e..432409c 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -3,12 +3,15 @@ import { ShoppingCartClearDialog } from '@/components/storage/ShoppingCartClearD import { ShoppingCartTable } from '@/components/storage/ShoppingCartTable'; import { useTranslations } from 'next-intl'; import { unstable_setRequestLocale } from 'next-intl/server'; +import { use } from 'react'; -export default function StorageShoppingCartPage({ - params: { locale }, -}: { - params: { locale: string }; +export default function StorageShoppingCartPage(props: { + params: Promise<{ locale: string }>; }) { + const params = use(props.params); + + const { locale } = params; + unstable_setRequestLocale(locale); const t = useTranslations('storage.shoppingCart'); const tLoanForm = useTranslations('storage.loanForm'); diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index 0d842cf..d69d777 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -7,7 +7,7 @@ import { Inter, Montserrat } from 'next/font/google'; type LocaleLayoutProps = { children: React.ReactNode; - params: { locale: string }; + params: Promise<{ locale: string }>; }; const inter = Inter({ @@ -30,9 +30,13 @@ export const viewport: Viewport = { themeColor: '#0c0a09', }; -export async function generateMetadata({ - params: { locale }, -}: Omit) { +export async function generateMetadata( + props: Omit, +) { + const params = await props.params; + + const { locale } = params; + const t = await getTranslations({ locale, namespace: 'meta' }); return { @@ -69,10 +73,13 @@ export async function generateMetadata({ }; } -export default function LocaleLayout({ - children, - params: { locale }, -}: LocaleLayoutProps) { +export default async function LocaleLayout(props: LocaleLayoutProps) { + const params = await props.params; + + const { locale } = params; + + const { children } = props; + unstable_setRequestLocale(locale); return ( { - const heads = new Headers(headers()); + const heads = new Headers(headers() as unknown as UnsafeUnwrappedHeaders); heads.set('x-trpc-source', 'rsc'); return createTRPCContext({ diff --git a/src/server/auth/user.ts b/src/server/auth/user.ts index 26cba65..b7947e3 100644 --- a/src/server/auth/user.ts +++ b/src/server/auth/user.ts @@ -3,13 +3,14 @@ import { cookies } from 'next/headers'; import { cache } from 'react'; const getUser = cache(async () => { - const sessionId = cookies().get(auth.sessionCookieName)?.value ?? null; + const sessionId = + (await cookies()).get(auth.sessionCookieName)?.value ?? null; if (!sessionId) return null; const { user, session } = await auth.validateSession(sessionId); try { if (session?.fresh) { const sessionCookie = auth.createSessionCookie(session.id); - cookies().set( + (await cookies()).set( sessionCookie.name, sessionCookie.value, sessionCookie.attributes, @@ -17,7 +18,7 @@ const getUser = cache(async () => { } if (!session) { const sessionCookie = auth.createBlankSessionCookie(); - cookies().set( + (await cookies()).set( sessionCookie.name, sessionCookie.value, sessionCookie.attributes, From 7a6a4c0f6b3572abc2368e3db6f34fb23d168a51 Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Sun, 27 Oct 2024 15:15:08 +0100 Subject: [PATCH 02/12] feat: update dependencies --- .env.example | 1 + .github/workflows/code-quality.yml | 1 + Dockerfile | 2 + README.md | 5 +- bun.lockb | Bin 225484 -> 245476 bytes drizzle.config.ts | 4 +- lighthouserc.cjs | 4 +- messages/en.json | 10 +- messages/no.json | 10 +- next-sitemap.config.js | 8 - next.config.js => next.config.ts | 5 +- package.json | 21 +- postcss.config.js => postcss.config.ts | 5 +- src/app/[locale]/(default)/about/page.tsx | 4 +- src/app/[locale]/(default)/events/page.tsx | 4 +- src/app/[locale]/(default)/layout.tsx | 4 +- .../[locale]/(default)/news/(main)/layout.tsx | 4 +- .../[locale]/(default)/news/(main)/page.tsx | 4 +- .../(default)/news/[article]/page.tsx | 4 +- src/app/[locale]/(default)/page.tsx | 7 +- .../(default)/storage/(main)/layout.tsx | 4 +- .../(default)/storage/(main)/page.tsx | 4 +- .../storage/shopping-cart/layout.tsx | 4 +- .../(default)/storage/shopping-cart/page.tsx | 4 +- src/app/[locale]/layout.tsx | 9 +- src/app/robots.ts | 12 + src/app/sitemap.ts | 43 ++++ .../composites/PaginationCarousel.tsx | 132 +++++++++-- .../composites/PaginationCarouselClient.tsx | 134 ----------- .../providers/IntlClientProvider.tsx | 20 ++ .../providers/IntlErrorProvider.tsx | 17 -- src/components/providers/RootProviders.tsx | 4 +- src/components/providers/ThemeProvider.tsx | 4 + src/components/storage/AddToCartButton.tsx | 4 +- src/components/storage/LoanForm.tsx | 111 +++++---- src/components/ui/Calendar.tsx | 216 ++++++++++++++---- src/components/ui/DatePicker.tsx | 9 +- src/components/ui/Form.tsx | 196 ++++++++-------- src/components/ui/Loader.tsx | 30 --- src/components/ui/ScrollArea.tsx | 48 ++++ src/components/ui/Spinner.tsx | 31 +++ src/{env.js => env.ts} | 0 src/lib/api/server.ts | 7 +- src/lib/locale/index.ts | 12 +- tailwind.config.ts | 4 +- tsconfig.json | 2 +- 46 files changed, 701 insertions(+), 467 deletions(-) delete mode 100644 next-sitemap.config.js rename next.config.js => next.config.ts (68%) rename postcss.config.js => postcss.config.ts (53%) create mode 100644 src/app/robots.ts create mode 100644 src/app/sitemap.ts delete mode 100644 src/components/composites/PaginationCarouselClient.tsx create mode 100644 src/components/providers/IntlClientProvider.tsx delete mode 100644 src/components/providers/IntlErrorProvider.tsx delete mode 100644 src/components/ui/Loader.tsx create mode 100644 src/components/ui/ScrollArea.tsx create mode 100644 src/components/ui/Spinner.tsx rename src/{env.js => env.ts} (100%) diff --git a/.env.example b/.env.example index 67a64b3..d0b5591 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,7 @@ # General NODE_ENV="development" +NODE_OPTIONS="--max_old_space_size=16384" NEXT_TELEMETRY_DISABLED="true" NEXT_PUBLIC_SITE_URL="http://localhost:3000" diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 841aaa2..344776d 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -21,6 +21,7 @@ jobs: name: Performance Audit runs-on: ubuntu-latest env: + CI: true NEXT_TELEMETRY_DISABLED: true NODE_ENV: "production" DATABASE_HOST: "localhost" diff --git a/Dockerfile b/Dockerfile index b16432f..c47daf3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . +ENV CI=true ENV NODE_ENV=production ENV SKIP_ENV_VALIDATION=true @@ -27,6 +28,7 @@ RUN bun run build FROM base AS runner WORKDIR /app +ENV CI=true ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=true ENV SKIP_ENV_VALIDATION=true diff --git a/README.md b/README.md index ddba536..8632b04 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,9 @@ Here is a list of documentation to help you get started: - [Next-intl](https://next-intl-docs.vercel.app/) - Internationalization library - [nuqs](https://nuqs.47ng.com/docs/installation) - Easy to use query params - [BlockNote](https://www.blocknotejs.org/docs) - Tool for markdown textboxes -- [React Hook Form](https://react-hook-form.com/get-started) - When we need to handle form validation - [Tanstack Query](https://tanstack.com/query/latest/docs/framework/react/overview) - TRPC wraps Tanstack Query which is how we fetch data from the backend +- [Tanstack Table](https://tanstack.com/table/latest/docs/introduction) - For dynamic tables with filtering, sorting, pagination etc +- [Tanstack Form](https://tanstack.com/form/latest/docs/overview) - When we need to handle form validation #### Styling @@ -28,7 +29,7 @@ Here is a list of documentation to help you get started: ### Backend - [TRPC](https://trpc.io/docs) - Tool for creating API endpoints as functions -- [Lucia](https://lucia-auth.com) - Authentication library +- [Lucia](https://lucia-auth.com) - Authentication learning resource (former library) - [Drizzle](https://orm.drizzle.team/docs/overview) - ORM for interacting with the database (Postgres under the hood) - [s3-client](https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3) - AWS S3 client for uploading files diff --git a/bun.lockb b/bun.lockb index 74bddeac182145697a0cada4f09d62078b817f67..62cb74156a6e64d24b28e015a2a11df32892b0cd 100755 GIT binary patch delta 57532 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 @@ -21,6 +21,6 @@ export default async function AboutPage(props: { const { locale } = params; - unstable_setRequestLocale(locale); + setRequestLocale(locale); return
this should be about page
; } diff --git a/src/app/[locale]/(default)/events/page.tsx b/src/app/[locale]/(default)/events/page.tsx index 17ff759..3eb4011 100644 --- a/src/app/[locale]/(default)/events/page.tsx +++ b/src/app/[locale]/(default)/events/page.tsx @@ -1,4 +1,4 @@ -import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; export async function generateMetadata(props: { params: Promise<{ locale: string }>; @@ -21,6 +21,6 @@ export default async function EventsPage(props: { const { locale } = params; - unstable_setRequestLocale(locale); + setRequestLocale(locale); return
This should be events page
; } diff --git a/src/app/[locale]/(default)/layout.tsx b/src/app/[locale]/(default)/layout.tsx index e90b9f7..b9fc1ae 100644 --- a/src/app/[locale]/(default)/layout.tsx +++ b/src/app/[locale]/(default)/layout.tsx @@ -1,7 +1,7 @@ import { Footer } from '@/components/layout/Footer'; import { Header } from '@/components/layout/Header'; import { Main } from '@/components/layout/Main'; -import { unstable_setRequestLocale } from 'next-intl/server'; +import { setRequestLocale } from 'next-intl/server'; type DefaultLayoutProps = { children: React.ReactNode; @@ -15,7 +15,7 @@ export default async function DefaultLayout(props: DefaultLayoutProps) { const { children } = props; - unstable_setRequestLocale(locale); + setRequestLocale(locale); return ( <>
diff --git a/src/app/[locale]/(default)/news/(main)/layout.tsx b/src/app/[locale]/(default)/news/(main)/layout.tsx index bef72bc..6991c17 100644 --- a/src/app/[locale]/(default)/news/(main)/layout.tsx +++ b/src/app/[locale]/(default)/news/(main)/layout.tsx @@ -1,6 +1,6 @@ import { SquarePenIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; -import { unstable_setRequestLocale } from 'next-intl/server'; +import { setRequestLocale } from 'next-intl/server'; import { use } from 'react'; import { Link } from '@/lib/locale/navigation'; @@ -19,7 +19,7 @@ export default function NewsHeaderLayout(props: NewsHeaderLayoutProps) { const { children } = props; - unstable_setRequestLocale(locale); + setRequestLocale(locale); const t = useTranslations('news'); return ( <> diff --git a/src/app/[locale]/(default)/news/(main)/page.tsx b/src/app/[locale]/(default)/news/(main)/page.tsx index 2dc84fc..082e444 100644 --- a/src/app/[locale]/(default)/news/(main)/page.tsx +++ b/src/app/[locale]/(default)/news/(main)/page.tsx @@ -1,6 +1,6 @@ import { articleMockData as articleData } from '@/mock-data/article'; import { useTranslations } from 'next-intl'; -import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import { createSearchParamsCache, parseAsInteger } from 'nuqs/server'; import { Suspense, use } from 'react'; @@ -33,7 +33,7 @@ export default function NewsPage(props: { const { locale } = params; - unstable_setRequestLocale(locale); + setRequestLocale(locale); const t = useTranslations('ui'); const searchParamsCache = createSearchParamsCache({ [t('page')]: parseAsInteger.withDefault(1), diff --git a/src/app/[locale]/(default)/news/[article]/page.tsx b/src/app/[locale]/(default)/news/[article]/page.tsx index 2fa59ea..4b7a7db 100644 --- a/src/app/[locale]/(default)/news/[article]/page.tsx +++ b/src/app/[locale]/(default)/news/[article]/page.tsx @@ -3,7 +3,7 @@ import { authorMockData as authorData, } from '@/mock-data/article'; import { useTranslations } from 'next-intl'; -import { unstable_setRequestLocale } from 'next-intl/server'; +import { setRequestLocale } from 'next-intl/server'; import Image from 'next/image'; import { notFound } from 'next/navigation'; import { use } from 'react'; @@ -35,7 +35,7 @@ export default function ArticlePage(props: { params: Promise<{ locale: string; article: string }>; }) { const params = use(props.params); - unstable_setRequestLocale(params.locale); + setRequestLocale(params.locale); const t = useTranslations('news'); const article = articleData.find( diff --git a/src/app/[locale]/(default)/page.tsx b/src/app/[locale]/(default)/page.tsx index a015cbc..e04b2e7 100644 --- a/src/app/[locale]/(default)/page.tsx +++ b/src/app/[locale]/(default)/page.tsx @@ -1,15 +1,12 @@ import { HelloWorld } from '@/components/home/HelloWorld'; import { api } from '@/lib/api/server'; -import { unstable_setRequestLocale } from 'next-intl/server'; +import { setRequestLocale } from 'next-intl/server'; export default async function HomePage(props: { params: Promise<{ locale: string }>; }) { const params = await props.params; - - const { locale } = params; - - unstable_setRequestLocale(locale); + setRequestLocale(params.locale); const hello = await api.test.helloWorld(); return (
diff --git a/src/app/[locale]/(default)/storage/(main)/layout.tsx b/src/app/[locale]/(default)/storage/(main)/layout.tsx index 649fc2d..86d67a5 100644 --- a/src/app/[locale]/(default)/storage/(main)/layout.tsx +++ b/src/app/[locale]/(default)/storage/(main)/layout.tsx @@ -4,7 +4,7 @@ import { SortSelector } from '@/components/composites/SortSelector'; import { SelectorsSkeleton } from '@/components/storage/SelectorsSkeleton'; import { ShoppingCartLink } from '@/components/storage/ShoppingCartLink'; import { useTranslations } from 'next-intl'; -import { unstable_setRequestLocale } from 'next-intl/server'; +import { setRequestLocale } from 'next-intl/server'; import { Suspense, use } from 'react'; type StorageLayoutProps = { @@ -19,7 +19,7 @@ export default function StorageLayout(props: StorageLayoutProps) { const { children } = props; - unstable_setRequestLocale(locale); + setRequestLocale(locale); const t = useTranslations('storage'); const tUi = useTranslations('ui'); diff --git a/src/app/[locale]/(default)/storage/(main)/page.tsx b/src/app/[locale]/(default)/storage/(main)/page.tsx index eedbae3..ad6e244 100644 --- a/src/app/[locale]/(default)/storage/(main)/page.tsx +++ b/src/app/[locale]/(default)/storage/(main)/page.tsx @@ -1,6 +1,6 @@ import { items } from '@/mock-data/items'; import { useTranslations } from 'next-intl'; -import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import { createSearchParamsCache, parseAsInteger } from 'nuqs/server'; import { use } from 'react'; @@ -30,7 +30,7 @@ export default function StoragePage(props: { const { locale } = params; - unstable_setRequestLocale(locale); + setRequestLocale(locale); const t = useTranslations('ui'); const itemsPerPage = 12; diff --git a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx index c2075f2..046372a 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx @@ -2,7 +2,7 @@ import { Button } from '@/components/ui/Button'; import { Link } from '@/lib/locale/navigation'; import { ArrowLeftIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; -import { unstable_setRequestLocale } from 'next-intl/server'; +import { setRequestLocale } from 'next-intl/server'; import { use } from 'react'; type ShoppingCartLayoutProps = { @@ -17,7 +17,7 @@ export default function StorageLayout(props: ShoppingCartLayoutProps) { const { children } = props; - unstable_setRequestLocale(locale); + setRequestLocale(locale); const t = useTranslations('storage.shoppingCart'); return ( <> diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 432409c..9ef061c 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -2,7 +2,7 @@ import { BorrowDialog } from '@/components/storage/BorrowDialog'; import { ShoppingCartClearDialog } from '@/components/storage/ShoppingCartClearDialog'; import { ShoppingCartTable } from '@/components/storage/ShoppingCartTable'; import { useTranslations } from 'next-intl'; -import { unstable_setRequestLocale } from 'next-intl/server'; +import { setRequestLocale } from 'next-intl/server'; import { use } from 'react'; export default function StorageShoppingCartPage(props: { @@ -12,7 +12,7 @@ export default function StorageShoppingCartPage(props: { const { locale } = params; - unstable_setRequestLocale(locale); + setRequestLocale(locale); const t = useTranslations('storage.shoppingCart'); const tLoanForm = useTranslations('storage.loanForm'); diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index d69d777..155f06b 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -1,8 +1,7 @@ import { RootProviders } from '@/components/providers/RootProviders'; import { routing } from '@/lib/locale'; import { cx } from '@/lib/utils'; -import type { Viewport } from 'next'; -import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import { Inter, Montserrat } from 'next/font/google'; type LocaleLayoutProps = { @@ -26,10 +25,6 @@ export function generateStaticParams() { return routing.locales.map((locale) => ({ locale })); } -export const viewport: Viewport = { - themeColor: '#0c0a09', -}; - export async function generateMetadata( props: Omit, ) { @@ -80,7 +75,7 @@ export default async function LocaleLayout(props: LocaleLayoutProps) { const { children } = props; - unstable_setRequestLocale(locale); + setRequestLocale(locale); return ( [0]['href']; + +function getEntry(href: Href, changefreq: string, priority: number) { + return { + url: getUrl(href, routing.defaultLocale), + lastModified: new Date(), + changefreq, + priority, + alternates: { + languages: Object.fromEntries( + routing.locales.map((locale) => [locale, getUrl(href, locale)]), + ), + }, + }; +} + +function getUrl(href: Href, locale: (typeof routing.locales)[number]) { + const pathname = getPathname({ locale, href }); + return `${env.NEXT_PUBLIC_SITE_URL}${pathname}`; +} + +export default function sitemap(): MetadataRoute.Sitemap { + return [ + getEntry('/', 'yearly', 1.0), + getEntry('/about', 'monthly', 0.8), + getEntry('/news', 'weekly', 0.7), + getEntry( + { + pathname: '/news/[article]', + params: { article: '1' }, + }, + 'daily', + 0.4, + ), + getEntry('/events', 'weekly', 0.7), + getEntry('/storage', 'daily', 0.4), + ]; +} diff --git a/src/components/composites/PaginationCarousel.tsx b/src/components/composites/PaginationCarousel.tsx index 9ddd538..3457224 100644 --- a/src/components/composites/PaginationCarousel.tsx +++ b/src/components/composites/PaginationCarousel.tsx @@ -1,22 +1,126 @@ -import { PaginationCarouselClient } from '@/components/composites/PaginationCarouselClient'; +'use client'; + +import { + Pagination, + PaginationContent, + PaginationEllipsis, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from '@/components/ui/Pagination'; +import { cx } from '@/lib/utils'; import { useTranslations } from 'next-intl'; +import { parseAsInteger, useQueryState } from 'nuqs'; + +type PaginationCarouselProps = { + className?: string; + totalPages: number; +}; function PaginationCarousel({ - ...props -}: { className?: string; totalPages: number }) { + className, + totalPages, +}: PaginationCarouselProps) { const t = useTranslations('ui'); + const [page, setPage] = useQueryState( + t('page'), + parseAsInteger.withDefault(1).withOptions({ shallow: false }), + ); + + function handlePrevious(e: React.MouseEvent) { + e.preventDefault(); + if (page > 1) { + void setPage(page - 1); + } + } + + function handleNext(e: React.MouseEvent) { + e.preventDefault(); + if (page < totalPages) { + void setPage(page + 1); + } + } + + function handlePageClick( + e: React.MouseEvent, + pageNum: number, + ) { + e.preventDefault(); + void setPage(pageNum); + } + + let pagesToDisplay = []; + if (page === 1) { + pagesToDisplay = [1, 2, 3].filter((pageNum) => pageNum <= totalPages); + } else if (page === totalPages) { + pagesToDisplay = [totalPages - 2, totalPages - 1, totalPages].filter( + (pageNum) => pageNum >= 1, + ); + } else { + pagesToDisplay = [page - 1, page, page + 1]; + } + + const lastPage = pagesToDisplay[pagesToDisplay.length - 1]; + return ( - + + + + + + {pagesToDisplay[0] !== undefined && pagesToDisplay[0] > 1 && ( + + + + )} + {pagesToDisplay.map( + (pageNum) => + pageNum > 0 && + pageNum <= totalPages && ( + + handlePageClick(e, pageNum)} + isActive={pageNum === page} + > + {pageNum} + + + ), + )} + {lastPage !== undefined && lastPage < totalPages && ( + + + + )} + + + + + ); } diff --git a/src/components/composites/PaginationCarouselClient.tsx b/src/components/composites/PaginationCarouselClient.tsx deleted file mode 100644 index 4693b24..0000000 --- a/src/components/composites/PaginationCarouselClient.tsx +++ /dev/null @@ -1,134 +0,0 @@ -'use client'; - -import { - Pagination, - PaginationContent, - PaginationEllipsis, - PaginationItem, - PaginationLink, - PaginationNext, - PaginationPrevious, -} from '@/components/ui/Pagination'; -import { cx } from '@/lib/utils'; -import { parseAsInteger, useQueryState } from 'nuqs'; - -type PaginationCarouselProps = { - className?: string; - totalPages: number; - t: { - goToPreviousPage: string; - previous: string; - morePages: string; - goToNextPage: string; - next: string; - page: string; - }; -}; - -function PaginationCarouselClient({ - className, - totalPages, - t, -}: PaginationCarouselProps) { - const [page, setPage] = useQueryState( - t.page, - parseAsInteger.withDefault(1).withOptions({ shallow: false }), - ); - - function handlePrevious(e: React.MouseEvent) { - e.preventDefault(); - if (page > 1) { - void setPage(page - 1); - } - } - - function handleNext(e: React.MouseEvent) { - e.preventDefault(); - if (page < totalPages) { - void setPage(page + 1); - } - } - - function handlePageClick( - e: React.MouseEvent, - pageNum: number, - ) { - e.preventDefault(); - void setPage(pageNum); - } - - let pagesToDisplay = []; - if (page === 1) { - pagesToDisplay = [1, 2, 3].filter((pageNum) => pageNum <= totalPages); - } else if (page === totalPages) { - pagesToDisplay = [totalPages - 2, totalPages - 1, totalPages].filter( - (pageNum) => pageNum >= 1, - ); - } else { - pagesToDisplay = [page - 1, page, page + 1]; - } - - const lastPage = pagesToDisplay[pagesToDisplay.length - 1]; - - return ( - - - - - - {pagesToDisplay[0] !== undefined && pagesToDisplay[0] > 1 && ( - - - - )} - {pagesToDisplay.map( - (pageNum) => - pageNum > 0 && - pageNum <= totalPages && ( - - handlePageClick(e, pageNum)} - isActive={pageNum === page} - > - {pageNum} - - - ), - )} - {lastPage !== undefined && lastPage < totalPages && ( - - - - )} - - - - - - ); -} - -export { PaginationCarouselClient }; diff --git a/src/components/providers/IntlClientProvider.tsx b/src/components/providers/IntlClientProvider.tsx new file mode 100644 index 0000000..28c5577 --- /dev/null +++ b/src/components/providers/IntlClientProvider.tsx @@ -0,0 +1,20 @@ +import { NextIntlClientProvider, useMessages } from 'next-intl'; + +type Props = { + children: React.ReactNode; + locale: string; +}; + +function IntlClientProvider({ children, locale }: Props) { + const { ui, error } = useMessages(); + return ( + } + > + {children} + + ); +} + +export { IntlClientProvider }; diff --git a/src/components/providers/IntlErrorProvider.tsx b/src/components/providers/IntlErrorProvider.tsx deleted file mode 100644 index 197c9c3..0000000 --- a/src/components/providers/IntlErrorProvider.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { NextIntlClientProvider, useMessages } from 'next-intl'; - -type Props = { - children: React.ReactNode; - locale: string; -}; - -function IntlErrorProvider({ children, locale }: Props) { - const { error } = useMessages(); - return ( - - {children} - - ); -} - -export { IntlErrorProvider }; diff --git a/src/components/providers/RootProviders.tsx b/src/components/providers/RootProviders.tsx index d4f5704..f701862 100644 --- a/src/components/providers/RootProviders.tsx +++ b/src/components/providers/RootProviders.tsx @@ -1,4 +1,4 @@ -import { IntlErrorProvider } from '@/components/providers/IntlErrorProvider'; +import { IntlClientProvider } from '@/components/providers/IntlClientProvider'; import { TRPCProvider } from '@/components/providers/TRPCProvider'; import { ThemeProvider } from '@/components/providers/ThemeProvider'; @@ -11,7 +11,7 @@ function RootProviders({ children, locale }: RootProvidersProps) { return ( - {children} + {children} ); diff --git a/src/components/providers/ThemeProvider.tsx b/src/components/providers/ThemeProvider.tsx index 39919b9..1b4753f 100644 --- a/src/components/providers/ThemeProvider.tsx +++ b/src/components/providers/ThemeProvider.tsx @@ -9,6 +9,10 @@ function ThemeProvider({ children }: { children: React.ReactNode }) { defaultTheme='system' enableSystem disableTransitionOnChange + themeColor={{ + light: 'hsl(0 0% 100%)', + dark: 'hsl(20 14.3% 4.1%)', + }} > {children} diff --git a/src/components/storage/AddToCartButton.tsx b/src/components/storage/AddToCartButton.tsx index c0009f7..aec7f2a 100644 --- a/src/components/storage/AddToCartButton.tsx +++ b/src/components/storage/AddToCartButton.tsx @@ -1,7 +1,7 @@ 'use client'; import { Button } from '@/components/ui/Button'; -import { Loader } from '@/components/ui/Loader'; +import { Spinner } from '@/components/ui/Spinner'; import { useLocalStorage } from '@/lib/hooks/useLocalStorage'; import { cx } from 'cva'; @@ -36,7 +36,7 @@ function AddToCartButton({ className, item, t }: AddToCartButtonProps) { ); if (isLoading) { - return ; + return ; } function updateCart() { diff --git a/src/components/storage/LoanForm.tsx b/src/components/storage/LoanForm.tsx index 81b26ac..9d77351 100644 --- a/src/components/storage/LoanForm.tsx +++ b/src/components/storage/LoanForm.tsx @@ -6,15 +6,13 @@ import { Form, FormControl, FormDescription, - FormField, FormItem, FormLabel, FormMessage, + useForm, } from '@/components/ui/Form'; import { Input } from '@/components/ui/Input'; -import { zodResolver } from '@hookform/resolvers/zod'; import { addDays, addWeeks, endOfWeek } from 'date-fns'; -import { useForm } from 'react-hook-form'; import { z } from 'zod'; const formSchema = z.object({ @@ -36,67 +34,68 @@ type LoanFormProps = { }; function LoanForm({ t }: LoanFormProps) { - const form = useForm>({ - resolver: zodResolver(formSchema), + const form = useForm(formSchema, { defaultValues: { phone: '', returnBy: new Date(), }, + onSubmit: ({ value }) => { + console.log(value); + }, }); - - function onSubmit(values: z.infer) { - // TODO: Add new loan to database - console.log(values); - } - return ( - <> -
- - ( - - {t.phoneNumber} - - - - {t.phoneNumberDescription} - - - )} - /> - ( - - {t.returnBy} - - - - {t.returnByDescription} - - - )} - /> - - - - + )} + + ); } diff --git a/src/components/ui/Calendar.tsx b/src/components/ui/Calendar.tsx index 905dbbc..38f12cf 100644 --- a/src/components/ui/Calendar.tsx +++ b/src/components/ui/Calendar.tsx @@ -1,64 +1,202 @@ 'use client'; -import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'; -import type * as React from 'react'; -import { DayPicker } from 'react-day-picker'; +import { + ChevronDownIcon, + ChevronLeftIcon, + ChevronRightIcon, + ChevronUpIcon, +} from 'lucide-react'; +import { useLocale } from 'next-intl'; +import { useFormatter, useTranslations } from 'next-intl'; +import { + DayPicker, + type DayPickerProps, + type DropdownOption, + type DropdownProps, +} from 'react-day-picker'; -import { buttonVariants } from '@/components/ui/Button'; +import { dayPickerLocales } from '@/lib/locale'; import { cx } from '@/lib/utils'; -export type CalendarProps = React.ComponentProps; +import { Button, buttonVariants } from '@/components/ui/Button'; +import { ScrollArea } from '@/components/ui/ScrollArea'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/Select'; + +export type CalendarProps = DayPickerProps; + +function Dropdown({ + value, + onChange, + options, + formatSelectedOption, +}: DropdownProps & { + formatSelectedOption?: (option?: DropdownOption) => string | undefined; +}) { + const selectedOption = options?.find((option) => option.value === value); + + function handleChange(value: string) { + const changeEvent = { + target: { value }, + } as React.ChangeEvent; + onChange?.(changeEvent); + } + + return ( + + ); +} function Calendar({ className, classNames, - showOutsideDays = true, - locale, + showOutsideDays = false, ...props }: CalendarProps) { + const t = useTranslations('ui'); + const format = useFormatter(); + const currentLocale = useLocale(); return ( , - IconRight: ({ ...props }) => , + DayButton({ modifiers, className, ...buttonProps }) { + return ( + diff --git a/src/components/ui/Form.tsx b/src/components/ui/Form.tsx index c945d9f..ae39eda 100644 --- a/src/components/ui/Form.tsx +++ b/src/components/ui/Form.tsx @@ -2,153 +2,155 @@ import type * as LabelPrimitive from '@radix-ui/react-label'; import { Slot } from '@radix-ui/react-slot'; -import * as React from 'react'; import { - Controller, - type ControllerProps, - type FieldPath, - type FieldValues, - FormProvider, - useFormContext, -} from 'react-hook-form'; + type FormOptions, + type ValidationError, + type Validator, + useForm, +} from '@tanstack/react-form'; +import { zodValidator } from '@tanstack/zod-form-adapter'; +import * as React from 'react'; +import type { z } from 'zod'; -import { Label } from '@/components/ui/Label'; import { cx } from '@/lib/utils'; -const Form = FormProvider; +import { Label } from '@/components/ui/Label'; + +function useFormWithZod< + TFormSchema extends z.ZodType, + TFormData extends object = z.infer, +>( + schema: TFormSchema, + options?: Omit< + FormOptions>, + 'validatorAdapter' + >, +) { + const form = useForm({ + validatorAdapter: zodValidator(), + validators: { + onChange: schema, + }, + ...options, + }); + + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + e.stopPropagation(); + void form.handleSubmit(); + } -type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath, -> = { - name: TName; + return { + ...form, + handleSubmit, + }; +} + +const Form = ({ + className, + ...props +}: React.HTMLAttributes) => { + return
; }; -const FormFieldContext = React.createContext( - {} as FormFieldContextValue, +type FormItemContextValue = { + id: string; + errors: ValidationError[]; +}; + +const FormItemContext = React.createContext( + {} as FormItemContextValue, ); -const FormField = < - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath, ->({ +const FormItem = ({ + className, + errors, ...props -}: ControllerProps) => { +}: React.HTMLAttributes & { errors: ValidationError[] }) => { + const id = React.useId(); + return ( - - - + +
+ ); }; -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext); +const useFormItem = () => { const itemContext = React.useContext(FormItemContext); - const { getFieldState, formState } = useFormContext(); - const fieldState = getFieldState(fieldContext.name, formState); - - if (!fieldContext) { - throw new Error('useFormField should be used within '); + if (!itemContext) { + throw new Error('useFormField should be used within '); } - const { id } = itemContext; + const { id, errors } = itemContext; return { id, - name: fieldContext.name, + errors, formItemId: `${id}-form-item`, formDescriptionId: `${id}-form-item-description`, formMessageId: `${id}-form-item-message`, - ...fieldState, }; }; -type FormItemContextValue = { - id: string; -}; - -const FormItemContext = React.createContext( - {} as FormItemContextValue, -); - -const FormItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => { - const id = React.useId(); - - return ( - -
- - ); -}); -FormItem.displayName = 'FormItem'; - -const FormLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => { - const { error, formItemId } = useFormField(); +const FormLabel = ({ + className, + ...props +}: React.ComponentPropsWithoutRef) => { + const { formItemId, errors } = useFormItem(); return (
@@ -78,13 +77,13 @@ export default function ArticlePage(props: { {t('readTime', { count: Math.ceil(minutes) })}   â€¢   - {article.date} + {data.date}
- {`${article.views} ${t('views')}`} + {`${data.views} ${t('views')}`}
-
{article.content}
+
{data.content}
); } diff --git a/src/app/[locale]/(default)/page.tsx b/src/app/[locale]/(default)/page.tsx index e04b2e7..2485554 100644 --- a/src/app/[locale]/(default)/page.tsx +++ b/src/app/[locale]/(default)/page.tsx @@ -2,11 +2,13 @@ import { HelloWorld } from '@/components/home/HelloWorld'; import { api } from '@/lib/api/server'; import { setRequestLocale } from 'next-intl/server'; -export default async function HomePage(props: { +export default async function HomePage({ + params, +}: { params: Promise<{ locale: string }>; }) { - const params = await props.params; - setRequestLocale(params.locale); + const { locale } = await params; + setRequestLocale(locale); const hello = await api.test.helloWorld(); return (
diff --git a/src/app/[locale]/(default)/storage/(main)/layout.tsx b/src/app/[locale]/(default)/storage/(main)/layout.tsx index 86d67a5..f321771 100644 --- a/src/app/[locale]/(default)/storage/(main)/layout.tsx +++ b/src/app/[locale]/(default)/storage/(main)/layout.tsx @@ -5,19 +5,18 @@ import { SelectorsSkeleton } from '@/components/storage/SelectorsSkeleton'; import { ShoppingCartLink } from '@/components/storage/ShoppingCartLink'; import { useTranslations } from 'next-intl'; import { setRequestLocale } from 'next-intl/server'; -import { Suspense, use } from 'react'; +import { Suspense } from 'react'; type StorageLayoutProps = { children: React.ReactNode; params: Promise<{ locale: string }>; }; -export default function StorageLayout(props: StorageLayoutProps) { - const params = use(props.params); - - const { locale } = params; - - const { children } = props; +export default async function StorageLayout({ + params, + children, +}: StorageLayoutProps) { + const { locale } = await params; setRequestLocale(locale); const t = useTranslations('storage'); diff --git a/src/app/[locale]/(default)/storage/(main)/loading.tsx b/src/app/[locale]/(default)/storage/(main)/loading.tsx index c510d4f..60b9b5d 100644 --- a/src/app/[locale]/(default)/storage/(main)/loading.tsx +++ b/src/app/[locale]/(default)/storage/(main)/loading.tsx @@ -2,7 +2,7 @@ import { PaginationCarouselSkeleton } from '@/components/composites/PaginationCa import { ItemCardSkeleton } from '@/components/storage/ItemCardSkeleton'; import { useId } from 'react'; -export default function StorageSkeleton() { +export default function StorageLoading() { return ( <>
diff --git a/src/app/[locale]/(default)/storage/(main)/page.tsx b/src/app/[locale]/(default)/storage/(main)/page.tsx index ad6e244..77bfeb7 100644 --- a/src/app/[locale]/(default)/storage/(main)/page.tsx +++ b/src/app/[locale]/(default)/storage/(main)/page.tsx @@ -1,18 +1,21 @@ import { items } from '@/mock-data/items'; import { useTranslations } from 'next-intl'; import { getTranslations, setRequestLocale } from 'next-intl/server'; -import { createSearchParamsCache, parseAsInteger } from 'nuqs/server'; -import { use } from 'react'; +import { + type SearchParams, + createSearchParamsCache, + parseAsInteger, +} from 'nuqs/server'; import { PaginationCarousel } from '@/components/composites/PaginationCarousel'; import { ItemCard } from '@/components/storage/ItemCard'; -export async function generateMetadata(props: { +export async function generateMetadata({ + params, +}: { params: Promise<{ locale: string }>; }) { - const params = await props.params; - - const { locale } = params; + const { locale } = await params; const t = await getTranslations({ locale, namespace: 'layout' }); @@ -21,14 +24,14 @@ export async function generateMetadata(props: { }; } -export default function StoragePage(props: { +export default async function StoragePage({ + params, + searchParams, +}: { params: Promise<{ locale: string }>; - searchParams: Promise>; + searchParams: Promise; }) { - const searchParams = use(props.searchParams); - const params = use(props.params); - - const { locale } = params; + const { locale } = await params; setRequestLocale(locale); const t = useTranslations('ui'); @@ -39,7 +42,7 @@ export default function StoragePage(props: { [t('page')]: parseAsInteger.withDefault(1), }); - const { [t('page')]: page = 1 } = searchParamsCache.parse(searchParams); + const { [t('page')]: page = 1 } = searchParamsCache.parse(await searchParams); return ( <> diff --git a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx index 046372a..ed08c83 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx @@ -3,19 +3,17 @@ import { Link } from '@/lib/locale/navigation'; import { ArrowLeftIcon } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { setRequestLocale } from 'next-intl/server'; -import { use } from 'react'; type ShoppingCartLayoutProps = { children: React.ReactNode; params: Promise<{ locale: string }>; }; -export default function StorageLayout(props: ShoppingCartLayoutProps) { - const params = use(props.params); - - const { locale } = params; - - const { children } = props; +export default async function StorageLayout({ + params, + children, +}: ShoppingCartLayoutProps) { + const { locale } = await params; setRequestLocale(locale); const t = useTranslations('storage.shoppingCart'); diff --git a/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx b/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx index 27310cd..80f54ed 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/loading.tsx @@ -2,7 +2,7 @@ import { ShoppingCartTableSkeleton } from '@/components/storage/ShoppingCartTabl import { Skeleton } from '@/components/ui/Skeleton'; import { useTranslations } from 'next-intl'; -export default function ShoppingCartSkeleton() { +export default function ShoppingCartLoading() { const t = useTranslations('storage.shoppingCart'); const tableMessages = { productId: t('productId'), diff --git a/src/components/providers/NuqsProvider.tsx b/src/components/providers/NuqsProvider.tsx new file mode 100644 index 0000000..c8c6b59 --- /dev/null +++ b/src/components/providers/NuqsProvider.tsx @@ -0,0 +1,7 @@ +import { NuqsAdapter } from 'nuqs/adapters/next/app'; + +function NuqsProvider({ children }: { children: React.ReactNode }) { + return {children}; +} + +export { NuqsProvider }; diff --git a/src/components/providers/RootProviders.tsx b/src/components/providers/RootProviders.tsx index f701862..c87f384 100644 --- a/src/components/providers/RootProviders.tsx +++ b/src/components/providers/RootProviders.tsx @@ -1,4 +1,5 @@ import { IntlClientProvider } from '@/components/providers/IntlClientProvider'; +import { NuqsProvider } from '@/components/providers/NuqsProvider'; import { TRPCProvider } from '@/components/providers/TRPCProvider'; import { ThemeProvider } from '@/components/providers/ThemeProvider'; @@ -11,7 +12,9 @@ function RootProviders({ children, locale }: RootProvidersProps) { return ( - {children} + + {children} + ); From 972141f9cb853207a63ff85836c3ddc3c256b16c Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:02:06 +0100 Subject: [PATCH 04/12] chore: migrate to getTranslations in async pages and layouts --- .../[locale]/(default)/news/(main)/layout.tsx | 5 ++--- src/app/[locale]/(default)/news/(main)/page.tsx | 3 +-- .../[locale]/(default)/news/[article]/page.tsx | 5 ++--- .../[locale]/(default)/storage/(main)/layout.tsx | 7 +++---- .../[locale]/(default)/storage/(main)/page.tsx | 3 +-- .../(default)/storage/shopping-cart/layout.tsx | 5 ++--- .../(default)/storage/shopping-cart/page.tsx | 16 +++++++--------- 7 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/app/[locale]/(default)/news/(main)/layout.tsx b/src/app/[locale]/(default)/news/(main)/layout.tsx index 9083b65..4664b3c 100644 --- a/src/app/[locale]/(default)/news/(main)/layout.tsx +++ b/src/app/[locale]/(default)/news/(main)/layout.tsx @@ -1,6 +1,5 @@ import { SquarePenIcon } from 'lucide-react'; -import { useTranslations } from 'next-intl'; -import { setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import { Link } from '@/lib/locale/navigation'; @@ -18,7 +17,7 @@ export default async function NewsHeaderLayout({ const { locale } = await params; setRequestLocale(locale); - const t = useTranslations('news'); + const t = await getTranslations('news'); return ( <>
diff --git a/src/app/[locale]/(default)/news/(main)/page.tsx b/src/app/[locale]/(default)/news/(main)/page.tsx index 21355c2..d6c8a98 100644 --- a/src/app/[locale]/(default)/news/(main)/page.tsx +++ b/src/app/[locale]/(default)/news/(main)/page.tsx @@ -1,5 +1,4 @@ import { articleMockData as articleData } from '@/mock-data/article'; -import { useTranslations } from 'next-intl'; import { getTranslations, setRequestLocale } from 'next-intl/server'; import { type SearchParams, @@ -37,7 +36,7 @@ export default async function NewsPage({ }) { const { locale } = await params; setRequestLocale(locale); - const t = useTranslations('ui'); + const t = await getTranslations('ui'); const searchParamsCache = createSearchParamsCache({ [t('page')]: parseAsInteger.withDefault(1), }); diff --git a/src/app/[locale]/(default)/news/[article]/page.tsx b/src/app/[locale]/(default)/news/[article]/page.tsx index e50c3ac..ca4cab0 100644 --- a/src/app/[locale]/(default)/news/[article]/page.tsx +++ b/src/app/[locale]/(default)/news/[article]/page.tsx @@ -2,8 +2,7 @@ import { articleMockData as articleData, authorMockData as authorData, } from '@/mock-data/article'; -import { useTranslations } from 'next-intl'; -import { setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import Image from 'next/image'; import { notFound } from 'next/navigation'; import readingTime from 'reading-time'; @@ -37,7 +36,7 @@ export default async function ArticlePage({ }) { const { locale, article } = await params; setRequestLocale(locale); - const t = useTranslations('news'); + const t = await getTranslations('news'); const data = articleData.find((a) => a.id === Number(article)); if (!data) { diff --git a/src/app/[locale]/(default)/storage/(main)/layout.tsx b/src/app/[locale]/(default)/storage/(main)/layout.tsx index f321771..5afa03c 100644 --- a/src/app/[locale]/(default)/storage/(main)/layout.tsx +++ b/src/app/[locale]/(default)/storage/(main)/layout.tsx @@ -3,8 +3,7 @@ import { SearchBar } from '@/components/composites/SearchBar'; import { SortSelector } from '@/components/composites/SortSelector'; import { SelectorsSkeleton } from '@/components/storage/SelectorsSkeleton'; import { ShoppingCartLink } from '@/components/storage/ShoppingCartLink'; -import { useTranslations } from 'next-intl'; -import { setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import { Suspense } from 'react'; type StorageLayoutProps = { @@ -19,8 +18,8 @@ export default async function StorageLayout({ const { locale } = await params; setRequestLocale(locale); - const t = useTranslations('storage'); - const tUi = useTranslations('ui'); + const t = await getTranslations('storage'); + const tUi = await getTranslations('ui'); // This does not make much sense with a backend, most likely the categories in the backend will have a name in both languages and an ID const categories = [ diff --git a/src/app/[locale]/(default)/storage/(main)/page.tsx b/src/app/[locale]/(default)/storage/(main)/page.tsx index 77bfeb7..e45da76 100644 --- a/src/app/[locale]/(default)/storage/(main)/page.tsx +++ b/src/app/[locale]/(default)/storage/(main)/page.tsx @@ -1,5 +1,4 @@ import { items } from '@/mock-data/items'; -import { useTranslations } from 'next-intl'; import { getTranslations, setRequestLocale } from 'next-intl/server'; import { type SearchParams, @@ -34,7 +33,7 @@ export default async function StoragePage({ const { locale } = await params; setRequestLocale(locale); - const t = useTranslations('ui'); + const t = await getTranslations('ui'); const itemsPerPage = 12; diff --git a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx index ed08c83..ce3981d 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/layout.tsx @@ -1,8 +1,7 @@ import { Button } from '@/components/ui/Button'; import { Link } from '@/lib/locale/navigation'; import { ArrowLeftIcon } from 'lucide-react'; -import { useTranslations } from 'next-intl'; -import { setRequestLocale } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; type ShoppingCartLayoutProps = { children: React.ReactNode; @@ -16,7 +15,7 @@ export default async function StorageLayout({ const { locale } = await params; setRequestLocale(locale); - const t = useTranslations('storage.shoppingCart'); + const t = await getTranslations('storage.shoppingCart'); return ( <>
diff --git a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx index 9ef061c..32d35a0 100644 --- a/src/app/[locale]/(default)/storage/shopping-cart/page.tsx +++ b/src/app/[locale]/(default)/storage/shopping-cart/page.tsx @@ -1,20 +1,18 @@ import { BorrowDialog } from '@/components/storage/BorrowDialog'; import { ShoppingCartClearDialog } from '@/components/storage/ShoppingCartClearDialog'; import { ShoppingCartTable } from '@/components/storage/ShoppingCartTable'; -import { useTranslations } from 'next-intl'; -import { setRequestLocale } from 'next-intl/server'; -import { use } from 'react'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; -export default function StorageShoppingCartPage(props: { +export default async function StorageShoppingCartPage({ + params, +}: { params: Promise<{ locale: string }>; }) { - const params = use(props.params); - - const { locale } = params; + const { locale } = await params; setRequestLocale(locale); - const t = useTranslations('storage.shoppingCart'); - const tLoanForm = useTranslations('storage.loanForm'); + const t = await getTranslations('storage.shoppingCart'); + const tLoanForm = await getTranslations('storage.loanForm'); const tableMessages = { tableDescription: t('tableDescription'), From a9ccfeac93d9b7d027f126b134f4f871d1f50915 Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:11:39 +0100 Subject: [PATCH 05/12] fix: params destructuring in more places --- src/app/[locale]/(default)/news/(main)/page.tsx | 8 ++++---- src/app/[locale]/(default)/storage/(main)/page.tsx | 1 - src/app/[locale]/layout.tsx | 11 ++++------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/app/[locale]/(default)/news/(main)/page.tsx b/src/app/[locale]/(default)/news/(main)/page.tsx index d6c8a98..72df9ec 100644 --- a/src/app/[locale]/(default)/news/(main)/page.tsx +++ b/src/app/[locale]/(default)/news/(main)/page.tsx @@ -13,12 +13,12 @@ import { ItemGrid } from '@/components/news/ItemGrid'; import { ItemGridSkeleton } from '@/components/news/ItemGridSkeleton'; import { Separator } from '@/components/ui/Separator'; -export async function generateMetadata(props: { +export async function generateMetadata({ + params, +}: { params: Promise<{ locale: string }>; }) { - const params = await props.params; - - const { locale } = params; + const { locale } = await params; const t = await getTranslations({ locale, namespace: 'layout' }); diff --git a/src/app/[locale]/(default)/storage/(main)/page.tsx b/src/app/[locale]/(default)/storage/(main)/page.tsx index e45da76..60da548 100644 --- a/src/app/[locale]/(default)/storage/(main)/page.tsx +++ b/src/app/[locale]/(default)/storage/(main)/page.tsx @@ -15,7 +15,6 @@ export async function generateMetadata({ params: Promise<{ locale: string }>; }) { const { locale } = await params; - const t = await getTranslations({ locale, namespace: 'layout' }); return { diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index 155f06b..fc9c103 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -25,13 +25,10 @@ export function generateStaticParams() { return routing.locales.map((locale) => ({ locale })); } -export async function generateMetadata( - props: Omit, -) { - const params = await props.params; - - const { locale } = params; - +export async function generateMetadata({ + params, +}: Omit) { + const { locale } = await params; const t = await getTranslations({ locale, namespace: 'meta' }); return { From 1bc882198c07c67ce815e248f1382ac5cce67cc2 Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:19:17 +0100 Subject: [PATCH 06/12] fix: locale specification to work in next 15 --- bun.lockb | Bin 240204 -> 240204 bytes src/lib/locale/navigation.ts | 4 ++-- src/lib/locale/request.ts | 11 ++++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/bun.lockb b/bun.lockb index 1545ccbd29e524e0888ca394da6f951267ee772e..b7288d1acdeb7b26e576e1a959ad25b193483995 100755 GIT binary patch delta 31 ncmX?eh40K2zJ?aYElhj;*cs!D^bGV&+K>1#Z9n42+z|}`%BKs( delta 31 jcmX?eh40K2zJ?aYElhj;*qIo>p#6v+)Al2N%pK7HxRMHX diff --git a/src/lib/locale/navigation.ts b/src/lib/locale/navigation.ts index 43e9e40..1dfa73f 100644 --- a/src/lib/locale/navigation.ts +++ b/src/lib/locale/navigation.ts @@ -1,5 +1,5 @@ import { routing } from '@/lib/locale'; -import { createLocalizedPathnamesNavigation } from 'next-intl/navigation'; +import { createNavigation } from 'next-intl/navigation'; export const { Link, redirect, usePathname, useRouter, getPathname } = - createLocalizedPathnamesNavigation(routing); + createNavigation(routing); diff --git a/src/lib/locale/request.ts b/src/lib/locale/request.ts index 5a5fb6e..7793d7a 100644 --- a/src/lib/locale/request.ts +++ b/src/lib/locale/request.ts @@ -1,10 +1,15 @@ import { routing } from '@/lib/locale'; import { getRequestConfig } from 'next-intl/server'; -import { notFound } from 'next/navigation'; -export default getRequestConfig(async ({ locale }) => { - if (!routing.locales.includes(locale as 'en')) notFound(); +export default getRequestConfig(async ({ requestLocale }) => { + let locale = await requestLocale; + + if (!locale || !routing.locales.includes(locale as 'en')) { + locale = routing.defaultLocale; + } + return { + locale, messages: (await import(`../../../messages/${locale}.json`)) .default as Messages, }; From a65126b559690fc65bd2ab0fe20dd5fb77e5c24d Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:28:18 +0100 Subject: [PATCH 07/12] chore: fix readme --- CONTRIBUTING.md | 3 ++- README.md | 11 ++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 655cd18..6c9af86 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,8 +80,9 @@ Here is a list of documentations that will help you contribute to the project: - [Next-intl](https://next-intl-docs.vercel.app/) - Internationalization library - [nuqs](https://nuqs.47ng.com/docs/installation) - Easy to use query params - [BlockNote](https://www.blocknotejs.org/docs) - Tool for markdown textboxes -- [React Hook Form](https://react-hook-form.com/get-started) - When we need to handle form validation - [Tanstack Query](https://tanstack.com/query/latest/docs/framework/react/overview) - TRPC wraps Tanstack Query which is how we fetch data from the backend +- [Tanstack Table](https://tanstack.com/table/latest/docs/introduction) - For dynamic tables with filtering, sorting, pagination etc +- [Tanstack Form](https://tanstack.com/form/latest/docs/overview) - When we need to handle form validation #### Styling diff --git a/README.md b/README.md index 3669887..1d687cd 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,9 @@ The overhauled website for the [Hackerspace NTNU](https://www.hackerspace-ntnu.no/) student organization. -## Did you encouter an issue with the website? +## Did you encounter an issue with the website? -- [React](https://react.dev/reference/react) - Library for building user interfaces -- [Next.js](https://nextjs.org/docs) - Framework for routing and server-side rendering -- [Next-intl](https://next-intl-docs.vercel.app/) - Internationalization library -- [nuqs](https://nuqs.47ng.com/docs/installation) - Easy to use query params -- [BlockNote](https://www.blocknotejs.org/docs) - Tool for markdown textboxes -- [Tanstack Query](https://tanstack.com/query/latest/docs/framework/react/overview) - TRPC wraps Tanstack Query which is how we fetch data from the backend -- [Tanstack Table](https://tanstack.com/table/latest/docs/introduction) - For dynamic tables with filtering, sorting, pagination etc -- [Tanstack Form](https://tanstack.com/form/latest/docs/overview) - When we need to handle form validation +Please report it as an [issue](https://github.com/hackerspace-ntnu/website-next/issues)! If the issue needs to be resolved as soon as possible, please contact a Hackerspace NTNU member. From 433de7dd04e198d17945d6931f59688dc7a4ee5d Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:31:59 +0100 Subject: [PATCH 08/12] chore: update lighthouse config --- lighthouserc.cjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lighthouserc.cjs b/lighthouserc.cjs index ad72291..6abc5ee 100644 --- a/lighthouserc.cjs +++ b/lighthouserc.cjs @@ -31,6 +31,7 @@ const config = { 'heading-order': 'off', 'largest-contentful-paint': 'off', 'render-blocking-resources': 'off', + 'target-size': 'off', }, }, { @@ -42,8 +43,12 @@ const config = { 'heading-order': 'off', 'largest-contentful-paint': 'off', 'render-blocking-resources': 'off', + 'target-size': 'off', interactive: 'off', 'uses-responsive-images': 'off', // Should be removed when we obtain images from backend + 'image-aspect-ratio': 'off', // Should be removed when we obtain images from backend + 'image-size-responsive': 'off', // Should be removed when we obtain images from backend + 'max-potential-fid': 'off', }, }, { @@ -55,9 +60,11 @@ const config = { 'heading-order': 'off', 'largest-contentful-paint': 'off', 'render-blocking-resources': 'off', + 'target-size': 'off', 'unused-javascript': 'off', 'cumulative-layout-shift': 'off', // We don't always know how many items are in the cart, which can lead to layout shifts when loading completes 'max-potential-fid': 'off', + 'image-aspect-ratio': 'off', // Should be removed when we obtain images from backend }, }, ], From 2fee9e2157524626ef4c6517c32e01c4960bc7cc Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:38:26 +0100 Subject: [PATCH 09/12] feat: update components and add comments (back) to make Martin happy --- bun.lockb | Bin 240204 -> 240628 bytes messages/en.json | 3 +- messages/no.json | 3 +- package.json | 1 + postcss.config.ts => postcss.config.js | 5 +- src/components/composites/ConfirmDialog.tsx | 50 ++--- src/components/composites/DatePicker.tsx | 121 ++++++++++++ .../composites/ResponsiveDialog.tsx | 187 ++++++++++++++++++ src/components/ui/Calendar.tsx | 6 + src/components/ui/DatePicker.tsx | 69 ------- src/components/ui/Drawer.tsx | 118 +++++++++++ src/components/ui/Form.tsx | 6 + src/lib/hooks/useMediaQuery.ts | 21 ++ tsconfig.json | 4 +- 14 files changed, 494 insertions(+), 100 deletions(-) rename postcss.config.ts => postcss.config.js (53%) create mode 100644 src/components/composites/DatePicker.tsx create mode 100644 src/components/composites/ResponsiveDialog.tsx delete mode 100644 src/components/ui/DatePicker.tsx create mode 100644 src/components/ui/Drawer.tsx create mode 100644 src/lib/hooks/useMediaQuery.ts diff --git a/bun.lockb b/bun.lockb index b7288d1acdeb7b26e576e1a959ad25b193483995..27c81c28b45db57704baa94b1aaae008e3b8b188 100755 GIT binary patch delta 46325 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 Nwyn}HyGhxDw!hjN0yY2u diff --git a/messages/en.json b/messages/en.json index f7f2cac..62e259c 100644 --- a/messages/en.json +++ b/messages/en.json @@ -20,7 +20,8 @@ "previousMonth": "Previous month", "selectMonth": "Select month", "selectYear": "Select year", - "pickDate": "Pick a date" + "pickDate": "Pick a date", + "dateFormat": "dd/MM/yyyy" }, "error": { "notFound": "404 - Page not found", diff --git a/messages/no.json b/messages/no.json index 4b4d878..0c5810a 100644 --- a/messages/no.json +++ b/messages/no.json @@ -20,7 +20,8 @@ "previousMonth": "Forrige måned", "selectMonth": "Velg måned", "selectYear": "Velg år", - "pickDate": "Velg en dato" + "pickDate": "Velg en dato", + "dateFormat": "dd.MM.yyyy" }, "error": { "notFound": "404 - Siden ble ikke funnet", diff --git a/package.json b/package.json index 3467193..dc172f9 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "reading-time": "^1.5.0", "superjson": "^2.2.1", "tailwind-merge": "^2.5.2", + "vaul": "^1.1.0", "zod": "^3.23.8" }, "devDependencies": { diff --git a/postcss.config.ts b/postcss.config.js similarity index 53% rename from postcss.config.ts rename to postcss.config.js index e845d75..2ef30fc 100644 --- a/postcss.config.ts +++ b/postcss.config.js @@ -1,6 +1,5 @@ -import type { Config } from 'postcss-load-config'; - -const config: Config = { +/** @type {import('postcss-load-config').Config} */ +const config = { plugins: { tailwindcss: {}, autoprefixer: {}, diff --git a/src/components/composites/ConfirmDialog.tsx b/src/components/composites/ConfirmDialog.tsx index 4a2c1b3..7f0d41b 100644 --- a/src/components/composites/ConfirmDialog.tsx +++ b/src/components/composites/ConfirmDialog.tsx @@ -1,16 +1,16 @@ 'use client'; -import { Button, type buttonVariants } from '@/components/ui/Button'; import { - Dialog, - DialogClose, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - DialogTrigger, -} from '@/components/ui/Dialog'; + ResponsiveDialog, + ResponsiveDialogClose, + ResponsiveDialogContent, + ResponsiveDialogDescription, + ResponsiveDialogFooter, + ResponsiveDialogHeader, + ResponsiveDialogTitle, + ResponsiveDialogTrigger, +} from '@/components/composites/ResponsiveDialog'; +import { Button, type buttonVariants } from '@/components/ui/Button'; import type { VariantProps } from '@/lib/utils'; import { useState } from 'react'; @@ -30,21 +30,23 @@ function ConfirmDialog({ confirmAction, t, ...props }: ConfirmDialogProps) { const [open, setOpen] = useState(false); return ( - - + + - + - - - + + + ); } diff --git a/src/components/composites/DatePicker.tsx b/src/components/composites/DatePicker.tsx new file mode 100644 index 0000000..4c1ca41 --- /dev/null +++ b/src/components/composites/DatePicker.tsx @@ -0,0 +1,121 @@ +'use client'; + +import { isValid, parse } from 'date-fns'; +import { CalendarIcon } from 'lucide-react'; +import { useTranslations } from 'next-intl'; +import { useFormatter } from 'next-intl'; +import * as React from 'react'; +import type { DayPickerProps } from 'react-day-picker'; + +import { cx } from '@/lib/utils'; + +import { Button } from '@/components/ui/Button'; +import { Calendar } from '@/components/ui/Calendar'; +import { Input } from '@/components/ui/Input'; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from '@/components/ui/Popover'; + +type DatePickerProps = { + className?: string; + side?: 'top' | 'bottom' | 'left' | 'right'; + avoidCollisions?: boolean; + date: Date | undefined; + setDate: (date: Date | undefined) => void; + id: string; +} & Omit; + +/** + * This is a sligtly modified version of shadcn's Date Picker built on top of Calendar. + * The component has a state, but also allows adding an additional date callback function which + * provides a way to have side effects and/or state updates on the parent component whenever a new date is selected. + * UPDATE: Now supports an input field so it actually works as a date picker in a form. State is passed to it via props + * so it works in a form. Also included i18n support. + */ +function DatePicker({ + className, + side, + avoidCollisions = true, + date, + setDate, + id, + ...props +}: DatePickerProps) { + const t = useTranslations('ui'); + const format = useFormatter(); + const [open, setOpen] = React.useState(false); + const [month, setMonth] = React.useState(date); + const [inputValue, setInputValue] = React.useState(''); + + function handleSelectDate(date: Date | undefined) { + if (!date) { + setInputValue(''); + setDate(undefined); + } else { + setDate(date); + setMonth(date); + setInputValue( + format.dateTime(date, { + day: 'numeric', + month: 'numeric', + year: 'numeric', + }), + ); + } + } + + function handleInputChange(e: React.ChangeEvent) { + setInputValue(e.target.value); + const parsedDate = parse(e.target.value, t('dateFormat'), new Date()); + + if (isValid(parsedDate)) { + setMonth(parsedDate); + } + setDate(parsedDate); + } + + return ( + +
+ + + + +
+ + + +
+ ); +} + +export { DatePicker }; diff --git a/src/components/composites/ResponsiveDialog.tsx b/src/components/composites/ResponsiveDialog.tsx new file mode 100644 index 0000000..417fe57 --- /dev/null +++ b/src/components/composites/ResponsiveDialog.tsx @@ -0,0 +1,187 @@ +'use client'; + +import type * as React from 'react'; + +import { useMediaQuery } from '@/lib/hooks/useMediaQuery'; +import { cx } from '@/lib/utils'; + +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/components/ui/Dialog'; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from '@/components/ui/Drawer'; + +interface BaseProps { + children: React.ReactNode; +} + +interface RootResponsiveDialogProps extends BaseProps { + open?: boolean; + onOpenChange?: (open: boolean) => void; +} + +interface ResponsiveDialogProps extends BaseProps { + className?: string; + asChild?: true; +} + +const desktop = '(min-width: 768px)'; + +/** + * This uses a drawer on mobile and a dialog on desktop so it is usually the preffered way to use dialogs in the app for a repsonsive experience. + */ +const ResponsiveDialog = ({ + children, + ...props +}: RootResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialog = isDesktop ? Dialog : Drawer; + + return {children}; +}; + +const ResponsiveDialogTrigger = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialogTrigger = isDesktop ? DialogTrigger : DrawerTrigger; + + return ( + + {children} + + ); +}; + +const ResponsiveDialogClose = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialogClose = isDesktop ? DialogClose : DrawerClose; + + return ( + + {children} + + ); +}; + +const ResponsiveDialogContent = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialogContent = isDesktop ? DialogContent : DrawerContent; + + return ( + + {children} + + ); +}; + +const ResponsiveDialogDescription = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialogDescription = isDesktop + ? DialogDescription + : DrawerDescription; + + return ( + + {children} + + ); +}; + +const ResponsiveDialogHeader = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialogHeader = isDesktop ? DialogHeader : DrawerHeader; + + return ( + + {children} + + ); +}; + +const ResponsiveDialogTitle = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialogTitle = isDesktop ? DialogTitle : DrawerTitle; + + return ( + + {children} + + ); +}; + +const ResponsiveDialogBody = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + return ( +
+ {children} +
+ ); +}; + +const ResponsiveDialogFooter = ({ + className, + children, + ...props +}: ResponsiveDialogProps) => { + const isDesktop = useMediaQuery(desktop); + const ResponsiveDialogFooter = isDesktop ? DialogFooter : DrawerFooter; + + return ( + + {children} + + ); +}; + +export { + ResponsiveDialog, + ResponsiveDialogTrigger, + ResponsiveDialogClose, + ResponsiveDialogContent, + ResponsiveDialogDescription, + ResponsiveDialogHeader, + ResponsiveDialogTitle, + ResponsiveDialogBody, + ResponsiveDialogFooter, +}; diff --git a/src/components/ui/Calendar.tsx b/src/components/ui/Calendar.tsx index 38f12cf..47517e9 100644 --- a/src/components/ui/Calendar.tsx +++ b/src/components/ui/Calendar.tsx @@ -30,6 +30,12 @@ import { export type CalendarProps = DayPickerProps; +/** + * This component is also customised a lot from its shadcn counterpart. + * We have updated to use React Day Picker V9 (which has a lot of breaking changes). + * Our version supports a dropdown for the month and year if enabled via the captionLayout prop. + * Also it uses the correct locale labels for everything based on the current locale. + */ function Dropdown({ value, onChange, diff --git a/src/components/ui/DatePicker.tsx b/src/components/ui/DatePicker.tsx deleted file mode 100644 index 8da0a95..0000000 --- a/src/components/ui/DatePicker.tsx +++ /dev/null @@ -1,69 +0,0 @@ -'use client'; - -import { format } from 'date-fns'; -import { CalendarIcon } from 'lucide-react'; -import * as React from 'react'; - -import { Button } from '@/components/ui/Button'; -import { Calendar } from '@/components/ui/Calendar'; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from '@/components/ui/Popover'; -import { cx } from '@/lib/utils'; -import { useTranslations } from 'next-intl'; -import type { Matcher } from 'react-day-picker'; - -type DatePickerProps = { - initialDate?: Date; - dateCallback?: (date: Date) => void; - disabled?: Matcher | Matcher[]; - buttonClassName?: string; -}; - -function DatePicker({ - initialDate, - dateCallback, - disabled, - buttonClassName, -}: DatePickerProps) { - const t = useTranslations('ui'); - const [date, setDate] = React.useState(initialDate ?? new Date()); - - function handleDateChange(date: Date | undefined) { - if (!date) return; - setDate(date); - if (dateCallback) { - dateCallback(date); - } - } - - return ( - - - - - - handleDateChange(date)} - disabled={disabled} - /> - - - ); -} - -export { DatePicker }; diff --git a/src/components/ui/Drawer.tsx b/src/components/ui/Drawer.tsx new file mode 100644 index 0000000..ec06859 --- /dev/null +++ b/src/components/ui/Drawer.tsx @@ -0,0 +1,118 @@ +'use client'; + +import * as React from 'react'; +import { Drawer as DrawerPrimitive } from 'vaul'; + +import { cx } from '@/lib/utils'; + +const Drawer = ({ + shouldScaleBackground = true, + ...props +}: React.ComponentProps) => ( + +); +Drawer.displayName = 'Drawer'; + +const DrawerTrigger = DrawerPrimitive.Trigger; + +const DrawerPortal = DrawerPrimitive.Portal; + +const DrawerClose = DrawerPrimitive.Close; + +const DrawerOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName; + +const DrawerContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + +
+ {children} + + +)); +DrawerContent.displayName = 'DrawerContent'; + +const DrawerHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DrawerHeader.displayName = 'DrawerHeader'; + +const DrawerFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DrawerFooter.displayName = 'DrawerFooter'; + +const DrawerTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DrawerTitle.displayName = DrawerPrimitive.Title.displayName; + +const DrawerDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DrawerDescription.displayName = DrawerPrimitive.Description.displayName; + +export { + Drawer, + DrawerPortal, + DrawerOverlay, + DrawerTrigger, + DrawerClose, + DrawerContent, + DrawerHeader, + DrawerFooter, + DrawerTitle, + DrawerDescription, +}; diff --git a/src/components/ui/Form.tsx b/src/components/ui/Form.tsx index ae39eda..30a0ebb 100644 --- a/src/components/ui/Form.tsx +++ b/src/components/ui/Form.tsx @@ -16,6 +16,12 @@ import { cx } from '@/lib/utils'; import { Label } from '@/components/ui/Label'; +/** + * This is a completely custom component and not the Form component from shadcn. This is because we are using Tanstack Form instead of React Hook Form. + * Short explanation: Tanstack Form is a much better form library than React Hook Form. It has better validation, better performance, and better documentation. + * (The last sentence was ChatGPT's opinion, the real reason is that React hook form does not support async validation which is nice to have) + * On how to use this look where it has been used in the codebase or ask Michael. + */ function useFormWithZod< TFormSchema extends z.ZodType, TFormData extends object = z.infer, diff --git a/src/lib/hooks/useMediaQuery.ts b/src/lib/hooks/useMediaQuery.ts new file mode 100644 index 0000000..4b8aece --- /dev/null +++ b/src/lib/hooks/useMediaQuery.ts @@ -0,0 +1,21 @@ +import { useEffect, useState } from 'react'; + +function useMediaQuery(query: string) { + const [value, setValue] = useState(false); + + useEffect(() => { + function onChange(event: MediaQueryListEvent) { + setValue(event.matches); + } + + const result = matchMedia(query); + result.addEventListener('change', onChange); + setValue(result.matches); + + return () => result.removeEventListener('change', onChange); + }, [query]); + + return value; +} + +export { useMediaQuery }; diff --git a/tsconfig.json b/tsconfig.json index 65c46f5..c63cfeb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,12 +30,12 @@ } }, "include": [ - ".eslintrc.js", - "postcss.config.ts", + "postcss.config.js", "next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js", + "**/*.cjs", ".next/types/**/*.ts" ], "exclude": ["node_modules"] From 8bfc80747cfb7206d5fee0a3eebb8436276c3611 Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:48:15 +0100 Subject: [PATCH 10/12] chore: update docs with Plate over BlockNote --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c9af86..dd0814b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,7 +79,7 @@ Here is a list of documentations that will help you contribute to the project: - [Next.js](https://nextjs.org/docs) - Framework for routing and server-side rendering - [Next-intl](https://next-intl-docs.vercel.app/) - Internationalization library - [nuqs](https://nuqs.47ng.com/docs/installation) - Easy to use query params -- [BlockNote](https://www.blocknotejs.org/docs) - Tool for markdown textboxes +- [Plate](https://platejs.org) - Tool for rich text editing - [Tanstack Query](https://tanstack.com/query/latest/docs/framework/react/overview) - TRPC wraps Tanstack Query which is how we fetch data from the backend - [Tanstack Table](https://tanstack.com/table/latest/docs/introduction) - For dynamic tables with filtering, sorting, pagination etc - [Tanstack Form](https://tanstack.com/form/latest/docs/overview) - When we need to handle form validation From 64d52164f6dde54bf25a85ea564282957282eacf Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Mon, 28 Oct 2024 08:08:07 +0100 Subject: [PATCH 11/12] chore: handle props better in date picker --- src/components/composites/DatePicker.tsx | 34 ++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/components/composites/DatePicker.tsx b/src/components/composites/DatePicker.tsx index 4c1ca41..4dbdb17 100644 --- a/src/components/composites/DatePicker.tsx +++ b/src/components/composites/DatePicker.tsx @@ -24,8 +24,18 @@ type DatePickerProps = { avoidCollisions?: boolean; date: Date | undefined; setDate: (date: Date | undefined) => void; - id: string; -} & Omit; + disabled?: boolean; +} & Omit< + DayPickerProps, + | 'fixedWeeks' + | 'today' + | 'selected' + | 'disabled' + | 'onSelect' + | 'autoFocus' + | 'mode' +> & + React.HTMLAttributes; /** * This is a sligtly modified version of shadcn's Date Picker built on top of Calendar. @@ -34,13 +44,20 @@ type DatePickerProps = { * UPDATE: Now supports an input field so it actually works as a date picker in a form. State is passed to it via props * so it works in a form. Also included i18n support. */ + function DatePicker({ className, side, avoidCollisions = true, date, setDate, - id, + captionLayout, + footer, + hideWeekdays, + numberOfMonths, + showOutsideDays, + showWeekNumber, + disabled, ...props }: DatePickerProps) { const t = useTranslations('ui'); @@ -81,10 +98,11 @@ function DatePicker({
@@ -111,7 +130,12 @@ function DatePicker({ selected={date} onSelect={handleSelectDate} autoFocus - {...props} + captionLayout={captionLayout} + footer={footer} + hideWeekdays={hideWeekdays} + numberOfMonths={numberOfMonths} + showOutsideDays={showOutsideDays} + showWeekNumber={showWeekNumber} /> From 5eb4d699c202be9ea5daffdaee2b291f390d3df1 Mon Sep 17 00:00:00 2001 From: Michael Brusegard <56915010+michaelbrusegard@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:49:31 +0100 Subject: [PATCH 12/12] chore: use cross-env for not running lefthook in CI --- Dockerfile | 2 -- bun.lockb | Bin 240628 -> 241188 bytes package.json | 3 ++- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index c47daf3..b16432f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,6 @@ WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . -ENV CI=true ENV NODE_ENV=production ENV SKIP_ENV_VALIDATION=true @@ -28,7 +27,6 @@ RUN bun run build FROM base AS runner WORKDIR /app -ENV CI=true ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=true ENV SKIP_ENV_VALIDATION=true diff --git a/bun.lockb b/bun.lockb index 27c81c28b45db57704baa94b1aaae008e3b8b188..d7633cf1b41eddcb62b3698a87f1a16dd2012bd5 100755 GIT binary patch delta 36919 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 PfvY8MU`;obxcUD8sAsee diff --git a/package.json b/package.json index dc172f9..42ebf4f 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "prepare": "lefthook install", + "prepare": "cross-env-shell '[ \"$NODE_ENV\" != \"production\" ] && lefthook install || exit 0'", "dev": "next dev --turbopack", "lint": "biome check --write", "prebuild": "next telemetry disable", @@ -67,6 +67,7 @@ "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", "autoprefixer": "^10.4.20", "client-only": "^0.0.1", + "cross-env": "^7.0.3", "drizzle-kit": "^0.24.1", "fluid-tailwind": "^1.0.3", "lefthook": "^1.7.14",