Skip to content

Commit

Permalink
add error.tsx
Browse files Browse the repository at this point in the history
  • Loading branch information
sadmann7 committed Jan 14, 2024
1 parent 2d4a7bb commit 1f9e1a2
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { ResetPasswordStep2Form } from "@/components/forms/reset-password-form-step2"
import { ResetPasswordConfirmForm } from "@/components/forms/reset-password-confirm-form"
import { Shell } from "@/components/shells/shell"

export const metadata: Metadata = {
Expand All @@ -17,7 +17,7 @@ export const metadata: Metadata = {
description: "Enter your email to reset your password",
}

export default function ResetPasswordStep2Page() {
export default function ResetPasswordConfirmPage() {
return (
<Shell className="max-w-lg">
<Card>
Expand All @@ -28,7 +28,7 @@ export default function ResetPasswordStep2Page() {
</CardDescription>
</CardHeader>
<CardContent>
<ResetPasswordStep2Form />
<ResetPasswordConfirmForm />
</CardContent>
</Card>
</Shell>
Expand Down
28 changes: 28 additions & 0 deletions src/app/(dashboard)/dashboard/stores/[storeId]/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client"

// Error components must be Client Components
import * as React from "react"

import { ErrorCard } from "@/components/cards/error-card"

export default function UpdateStoreError({
error,
reset,
}: {
error: Error
reset: () => void
}) {
React.useEffect(() => {
// Log the error to an error reporting service
console.error(error)
}, [error])

return (
<ErrorCard
title={error.name}
description={error.message}
reset={reset}
className="mx-auto max-w-md pt-20"
/>
)
}
6 changes: 2 additions & 4 deletions src/app/(dashboard)/dashboard/stores/[storeId]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,8 @@ export default async function StoreLayout({
/>
) : null}
</div>
<div className="space-y-8 overflow-auto">
<StoreTabs storeId={storeId} />
{children}
</div>
<StoreTabs storeId={storeId} />
<div className="overflow-hidden">{children}</div>
</Shell>
)
}
4 changes: 2 additions & 2 deletions src/app/(dashboard)/dashboard/stores/new/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Metadata } from "next"
import { redirect } from "next/navigation"
import { env } from "@/env.mjs"
import { currentUser } from "@clerk/nextjs"

import { getCacheduser } from "@/lib/fetchers/auth"
import {
Card,
CardContent,
Expand All @@ -25,7 +25,7 @@ export const metadata: Metadata = {
}

export default async function NewStorePage() {
const user = await currentUser()
const user = await getCacheduser()

if (!user) {
redirect("/signin")
Expand Down
2 changes: 2 additions & 0 deletions src/components/cards/error-card.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client"

import * as React from "react"
import Link from "next/link"
import { ExclamationTriangleIcon } from "@radix-ui/react-icons"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { PasswordInput } from "@/components/password-input"

type Inputs = z.infer<typeof resetPasswordSchema>

export function ResetPasswordStep2Form() {
export function ResetPasswordConfirmForm() {
const router = useRouter()
const { isLoaded, signIn, setActive } = useSignIn()
const [isPending, startTransition] = React.useTransition()
Expand Down
2 changes: 1 addition & 1 deletion src/components/forms/reset-password-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function ResetPasswordForm() {
})

if (firstFactor.status === "needs_first_factor") {
router.push("/signin/reset-password/step2")
router.push("/signin/reset-password/confirm")
toast.message("Check your email", {
description: "We sent you a 6-digit verification code.",
})
Expand Down
50 changes: 29 additions & 21 deletions src/components/pagers/store-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useRouter, useSelectedLayoutSegment } from "next/navigation"
import { Tabs, TabsList, TabsTrigger } from "@radix-ui/react-tabs"

import { cn } from "@/lib/utils"
import { ScrollArea } from "@/components/ui/scroll-area"
import { Separator } from "@/components/ui/separator"

interface StoreTabsProps {
Expand Down Expand Up @@ -46,32 +47,39 @@ export function StoreTabs({ storeId }: StoreTabsProps) {
return (
<Tabs
defaultValue={tabs.find((tab) => tab.isActive)?.href ?? tabs[0]?.href}
className="sticky top-0 z-30 w-full overflow-auto bg-background px-1"
className="sticky top-0 z-30 h-full w-full overflow-auto bg-background px-1"
onValueChange={(value) => router.push(value)}
>
<TabsList className="inline-flex items-center justify-center space-x-1.5 text-muted-foreground">
{tabs.map((tab) => (
<div
role="none"
key={tab.href}
className={cn(
"border-b-2 border-transparent py-1.5",
tab.isActive && "border-foreground"
)}
>
<TabsTrigger
value={tab.href}
<ScrollArea
orientation="horizontal"
className="pb-2.5"
scrollBarClassName="h-2"
>
<TabsList className="inline-flex items-center justify-center space-x-1.5 text-muted-foreground">
{tabs.map((tab) => (
<div
role="none"
key={tab.href}
className={cn(
"inline-flex items-center justify-center rounded-sm px-3 py-1.5 text-sm font-medium text-muted-foreground ring-offset-background transition-all hover:bg-muted hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
tab.isActive && "text-foreground"
"border-b-2 border-transparent py-1.5",
tab.isActive && "border-foreground"
)}
>
<Link href={tab.href}>{tab.title}</Link>
</TabsTrigger>
</div>
))}
</TabsList>
<Separator />
<TabsTrigger
value={tab.href}
className={cn(
"inline-flex items-center justify-center rounded-sm px-3 py-1.5 text-sm font-medium text-muted-foreground ring-offset-background transition-all hover:bg-muted hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
tab.isActive && "text-foreground"
)}
asChild
>
<Link href={tab.href}>{tab.title}</Link>
</TabsTrigger>
</div>
))}
</TabsList>
<Separator />
</ScrollArea>
</Tabs>
)
}
92 changes: 54 additions & 38 deletions src/lib/actions/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,52 +37,68 @@ export async function addStore(rawInput: z.infer<typeof extendedStoreSchema>) {
}

export async function updateStore(storeId: number, fd: FormData) {
const input = updateStoreSchema.parse({
name: fd.get("name"),
description: fd.get("description"),
})

const storeWithSameName = await db.query.stores.findFirst({
where: and(eq(stores.name, input.name), not(eq(stores.id, storeId))),
columns: {
id: true,
},
})

if (storeWithSameName) {
throw new Error("Store name already taken")
}
try {
const input = updateStoreSchema.parse({
name: fd.get("name"),
description: fd.get("description"),
})

await db
.update(stores)
.set({
name: input.name,
description: input.description,
const storeWithSameName = await db.query.stores.findFirst({
where: and(eq(stores.name, input.name), not(eq(stores.id, storeId))),
columns: {
id: true,
},
})
.where(eq(stores.id, storeId))

revalidateTag("user-stores")
revalidatePath(`/dashboard/stores/${storeId}`)
if (storeWithSameName) {
throw new Error("Store name already taken")
}

await db
.update(stores)
.set({
name: input.name,
description: input.description,
})
.where(eq(stores.id, storeId))

revalidateTag("user-stores")
revalidatePath(`/dashboard/stores/${storeId}`)

return {
message: "Store updated successfully.",
}
} catch (err) {
throw err instanceof Error
? err
: new Error("Something went wrong, please try again.")
}
}

export async function deleteStore(storeId: number) {
const store = await db.query.stores.findFirst({
where: eq(stores.id, storeId),
columns: {
id: true,
},
})
try {
const store = await db.query.stores.findFirst({
where: eq(stores.id, storeId),
columns: {
id: true,
},
})

if (!store) {
throw new Error("Store not found")
}
if (!store) {
throw new Error("Store not found")
}

await db.delete(stores).where(eq(stores.id, storeId))
await db.delete(stores).where(eq(stores.id, storeId))

// Delete all products of this store
await db.delete(products).where(eq(products.storeId, storeId))
// Delete all products of this store
await db.delete(products).where(eq(products.storeId, storeId))

const path = "/dashboard/stores"
revalidatePath(path)
redirect(path)
const path = "/dashboard/stores"
revalidatePath(path)
redirect(path)
} catch (err) {
throw err instanceof Error
? err
: new Error("Something went wrong, please try again.")
}
}
12 changes: 1 addition & 11 deletions src/lib/fetchers/auth.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import "server-only"

import { unstable_cache as cache } from "next/cache"
import { currentUser } from "@clerk/nextjs"

export async function getCacheduser() {
try {
return await cache(
async () => {
return currentUser()
},
["cached-user"],
{
revalidate: 900,
tags: ["cached-user"],
}
)()
return currentUser()
} catch (err) {
console.error(err)
return null
Expand Down

1 comment on commit 1f9e1a2

@vercel
Copy link

@vercel vercel bot commented on 1f9e1a2 Jan 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.