-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(kampus): new era with clerk & radix-ui themes (#717)
- Loading branch information
Showing
62 changed files
with
16,295 additions
and
22,286 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
NODE_ENV=development | ||
DATABASE_URL=mysql://kampus:kampus@localhost:3306/kampus?schema=public | ||
|
||
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= | ||
CLERK_SECRET_KEY= | ||
CLERK_WEBHOOK_SECRET= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { headers } from "next/headers"; | ||
import { type WebhookEvent } from "@clerk/nextjs/server"; | ||
import { Webhook } from "svix"; | ||
|
||
import { createClients } from "~/clients"; | ||
import { env } from "~/env"; | ||
|
||
export const dynamic = "force-dynamic"; | ||
|
||
const { prisma: db } = createClients(); | ||
|
||
export async function POST(req: Request) { | ||
// Get the headers | ||
const headerPayload = headers(); | ||
const svix_id = headerPayload.get("svix-id"); | ||
const svix_timestamp = headerPayload.get("svix-timestamp"); | ||
const svix_signature = headerPayload.get("svix-signature"); | ||
|
||
// If there are no headers, error out | ||
if (!svix_id || !svix_timestamp || !svix_signature) { | ||
return new Response("Error occured -- no svix headers", { | ||
status: 400, | ||
}); | ||
} | ||
|
||
// Get the body | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const payload = await req.json(); | ||
const body = JSON.stringify(payload); | ||
|
||
// Create a new SVIX instance with your secret. | ||
const wh = new Webhook(env.CLERK_WEBHOOK_SECRET); | ||
|
||
let evt: WebhookEvent; | ||
|
||
// Verify the payload with the headers | ||
try { | ||
evt = wh.verify(body, { | ||
"svix-id": svix_id, | ||
"svix-timestamp": svix_timestamp, | ||
"svix-signature": svix_signature, | ||
}) as WebhookEvent; | ||
} catch (err) { | ||
console.error("Error verifying webhook:", err); | ||
return new Response("Error occured", { | ||
status: 400, | ||
}); | ||
} | ||
|
||
if (evt) { | ||
// 👉 Parse the incoming event body into a ClerkWebhook object | ||
try { | ||
// 👉 `webhook.type` is a string value that describes what kind of event we need to handle | ||
|
||
// 👉 If the type is "user.updated" the important values in the database will be updated in the users table | ||
if (evt.type === "user.updated") { | ||
const email = evt.data.email_addresses[0]?.email_address; | ||
if (email) { | ||
await db.user.update({ | ||
where: { id: evt.data.id }, | ||
data: { | ||
username: evt.data.username || "", | ||
name: `${evt.data.first_name ?? ""} ${evt.data.last_name ?? ""}`.trim() || null, | ||
image: evt.data.image_url, | ||
email, | ||
}, | ||
}); | ||
} | ||
} | ||
|
||
// 👉 If the type is "user.created" create a record in the users table | ||
if (evt.type === "user.created") { | ||
const email = evt.data.email_addresses[0]?.email_address; | ||
if (email) { | ||
await db.user.create({ | ||
data: { | ||
id: evt.data.id, | ||
username: evt.data.username || "", | ||
name: `${evt.data.first_name ?? ""} ${evt.data.last_name ?? ""}`.trim() || null, | ||
image: evt.data.image_url, | ||
email, | ||
}, | ||
}); | ||
} | ||
} | ||
|
||
// 👉 If the type is "user.deleted", delete the user record and associated blocks | ||
if (evt.type === "user.deleted") { | ||
await db.user.delete({ | ||
where: { id: evt.data.id }, | ||
}); | ||
} | ||
|
||
return new Response("", { status: 201 }); | ||
} catch (err) { | ||
console.error(err); | ||
return new Response("Error occured -- processing webhook data", { | ||
status: 500, | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { authMiddleware } from "@clerk/nextjs"; | ||
|
||
export default authMiddleware({ | ||
// "/" will be accessible to all users | ||
publicRoutes: ["/", "/graphql", "/api/webhooks(.*)"], | ||
}); | ||
|
||
export const config = { | ||
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|graphql)(.*)"], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
"use client"; | ||
|
||
import { type PropsWithChildren } from "react"; | ||
import { Theme, ThemePanel } from "@radix-ui/themes"; | ||
|
||
import "@radix-ui/themes/styles.css"; | ||
|
||
import { ThemeProvider as KampusThemeProvider } from "@kampus/ui"; | ||
|
||
export function ThemeProvider(props: PropsWithChildren) { | ||
return ( | ||
<KampusThemeProvider attribute="class" defaultTheme="system" enableSystem> | ||
<Theme>{props.children}</Theme> | ||
</KampusThemeProvider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,24 @@ | ||
"use client"; | ||
|
||
import { useRouter } from "next/navigation"; | ||
|
||
import { Dialog, DialogContent } from "@kampus/ui"; | ||
import { Dialog, Theme } from "@radix-ui/themes"; | ||
|
||
import { CreatePanoPostForm } from "~/app/pano/CreatePanoPostForm"; | ||
|
||
export default function CreatePost({ searchParams }: { searchParams: { conn: string } }) { | ||
const router = useRouter(); | ||
|
||
return ( | ||
<Dialog open onOpenChange={() => router.back()}> | ||
<DialogContent className="sm:max-w-[425px]"> | ||
<CreatePanoPostForm connectionID={searchParams.conn} onCompleted={() => router.back()} /> | ||
</DialogContent> | ||
</Dialog> | ||
<Theme accentColor="amber"> | ||
<Dialog.Root open onOpenChange={() => router.back()}> | ||
<Dialog.Content className="sm:max-w-[425px]"> | ||
<Dialog.Title>Yeni Pano Girdisi</Dialog.Title> | ||
<Dialog.Description size="2" mb="4"> | ||
pano'yu zenginleştir :) | ||
</Dialog.Description> | ||
<CreatePanoPostForm connectionID={searchParams.conn} onCompleted={() => router.back()} /> | ||
</Dialog.Content> | ||
</Dialog.Root> | ||
</Theme> | ||
); | ||
} |
Oops, something went wrong.