Skip to content

Commit

Permalink
feat: add channels to CurrentGuildContext, switch to discord-api-type…
Browse files Browse the repository at this point in the history
…s library and implement WelcomeForm
  • Loading branch information
DownDev committed Mar 28, 2024
1 parent d130e44 commit 50ed262
Show file tree
Hide file tree
Showing 23 changed files with 2,200 additions and 1,029 deletions.
29 changes: 19 additions & 10 deletions app/contexts/CurrentGuildContext.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
"use client"

import { createContext, useContext } from "react"
import { PartialGuild } from "../types"
import { APIGuild, APIChannel } from "discord-api-types/v10"

const Context = createContext<PartialGuild | null>(null)
interface CurrentGuild {
guild: APIGuild
channels: APIChannel[]
}

const Context = createContext<CurrentGuild | null>(null)

export default function CurrentGuildContext({
guild,
channels,
children,
}: {
guild: PartialGuild
}: CurrentGuild & {
children: React.ReactNode
}) {
return <Context.Provider value={guild}>{children}</Context.Provider>
return (
<Context.Provider value={{ guild, channels }}>{children}</Context.Provider>
)
}

export function useCurrentGuild(): PartialGuild {
const guild = useContext(Context)
if (!guild) {
throw new Error("No GuildContext.Provider found when calling useGuild")
export function useCurrentGuild(): CurrentGuild {
const currentGuild = useContext(Context)
if (!currentGuild?.guild || !currentGuild.channels) {
throw new Error(
"No CurrentGuildContext.Provider found when calling useGuild"
)
}
return guild
return currentGuild
}
24 changes: 16 additions & 8 deletions app/dashboard/[guildId]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
"use client"

import { notFound } from "next/navigation"
import { useGuilds } from "@/app/contexts/GuildsContext"
import CurrentGuildContext from "@/app/contexts/CurrentGuildContext"
import { SidebarGuildList } from "@/components/GuildList"
import { Separator } from "@/components/ui/separator"
Expand All @@ -14,15 +11,26 @@ export default async function ServerLayout({
children: React.ReactNode
params: { guildId: string }
}) {
const { mutualGuilds } = useGuilds()
console.log(params.guildId)
const guild = mutualGuilds.find((guild) => guild.id === params.guildId)
if (!guild) {
const guildRes = await fetch(
`https://discord.com/api/guilds/${params.guildId}`,
{ headers: { authorization: `Bot ${process.env.TOKEN}` } }
)
if (!guildRes.ok) {
notFound()
}
const guild = await guildRes.json()

const channelsRes = await fetch(
`https://discord.com/api/guilds/${params.guildId}/channels`,
{ headers: { authorization: `Bot ${process.env.TOKEN}` } }
)
if (!channelsRes.ok) {
notFound()
}
const channels = await channelsRes.json()

return (
<CurrentGuildContext guild={guild}>
<CurrentGuildContext guild={guild} channels={channels}>
<div className="flex items-start h-[calc(100vh-65px)]">
<SidebarGuildList />
<Separator orientation="vertical" />
Expand Down
15 changes: 10 additions & 5 deletions app/dashboard/[guildId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"use client"
import WelcomeForm from "@/components/WelcomeForm"
import { ensureGuildExists } from "@/lib/db"

import { useCurrentGuild } from "@/app/contexts/CurrentGuildContext"
export const dynamic = "force-dynamic"

export default async function Dashboard() {
const guild = useCurrentGuild()
return <h1>{JSON.stringify(guild)}</h1>
export default async function Page({
params,
}: {
params: { guildId: string }
}) {
const guild = await ensureGuildExists(params.guildId)
return <WelcomeForm guild={guild} />
}
8 changes: 0 additions & 8 deletions app/types.ts

This file was deleted.

Binary file modified bun.lockb
Binary file not shown.
10 changes: 5 additions & 5 deletions components/GuildList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { PartialGuild } from "@/app/types"
import { APIPartialGuild } from "discord-api-types/v10"
import { Avatar, AvatarImage } from "./ui/avatar"
import { Label } from "./ui/label"
import Link from "next/link"
Expand Down Expand Up @@ -32,7 +32,7 @@ export function GuildButton({
size = "lg",
tooltipDirection = "bottom",
}: {
guild: PartialGuild
guild: APIPartialGuild
href: string
size?: "sm" | "lg"
tooltipDirection?: "top" | "bottom" | "left" | "right"
Expand Down Expand Up @@ -90,7 +90,7 @@ export function ChooseGuildList({
guilds,
redirectToDashboard,
}: {
guilds: PartialGuild[]
guilds: APIPartialGuild[]
redirectToDashboard?: boolean
}) {
if (!guilds.length) {
Expand Down Expand Up @@ -132,7 +132,7 @@ export function ServerListSkeleton() {
)
}

function AddToGuildButton({ guilds }: { guilds: PartialGuild[] }) {
function AddToGuildButton({ guilds }: { guilds: APIPartialGuild[] }) {
return (
<Dialog>
<DialogTrigger asChild>
Expand Down Expand Up @@ -169,7 +169,7 @@ function AddToGuildButton({ guilds }: { guilds: PartialGuild[] }) {

export function SidebarGuildList() {
const { mutualGuilds, inviteGuilds } = useGuilds()
const currentGuild = useCurrentGuild()
const { guild: currentGuild } = useCurrentGuild()

return (
<nav className="flex flex-col items-center justify-center">
Expand Down
10 changes: 5 additions & 5 deletions components/GuildSidebarSections.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client"

import { useCurrentGuild } from "@/app/contexts/CurrentGuildContext"
import { Button } from "./ui/button"
import { Separator } from "./ui/separator"
Expand All @@ -16,7 +18,7 @@ const SidebarElements: SidebarElement[] = [
]

function SidebarElement({ category }: { category: SidebarElement }) {
const guild = useCurrentGuild()
const { guild } = useCurrentGuild()

return (
<Button
Expand All @@ -32,13 +34,11 @@ function SidebarElement({ category }: { category: SidebarElement }) {
}

export default function GuildSidebarSections() {
const currentGuild = useCurrentGuild()
const { guild } = useCurrentGuild()

return (
<aside className="flex flex-col mx-4">
<span className="mx-1 mt-2 text-center font-bold">
{currentGuild.name}
</span>
<span className="mx-1 mt-2 text-center font-bold">{guild.name}</span>
<Separator className="my-2 bg-black dark:bg-white" />
{SidebarElements.map((category, i) => (
<SidebarElement key={i} category={category} />
Expand Down
80 changes: 80 additions & 0 deletions components/WelcomeForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use client"

import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Textarea } from "./ui/textarea"
import ChannelSelect from "./form/ChannelSelect"
import { addData } from "@/lib/actions"
import { Guild } from "@prisma/client"

const FormSchema = z.object({
welcomeChannel: z.string(),
welcomeMessage: z.string().min(2),
})

export default function WelcomeForm({ guild }: { guild: Guild }) {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
welcomeChannel: guild.welcomeChannel ?? undefined,
welcomeMessage: guild.welcomeMessage ?? undefined,
},
})

async function onSubmit(data: z.infer<typeof FormSchema>) {
console.log(data)
await addData(guild.id, data)
}

return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="welcomeChannel"
render={({ field }) => (
<FormItem>
<FormLabel>Welcome channel</FormLabel>
<ChannelSelect {...field} />
<FormDescription>Select a channel</FormDescription>
<FormMessage />
</FormItem>
)}
/>

<FormField
control={form.control}
name="welcomeMessage"
render={({ field }) => (
<FormItem>
<FormLabel>Welcome message</FormLabel>
<FormControl>
<Textarea
placeholder="Message"
className="resize-none"
{...field}
/>
</FormControl>
<FormDescription>
The message that will be sent to the welcome channel
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Save</Button>
</form>
</Form>
)
}
38 changes: 38 additions & 0 deletions components/form/ChannelSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use client"

import { useCurrentGuild } from "@/app/contexts/CurrentGuildContext"
import { FormControl } from "@/components/ui/form"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"

export default function ChannelSelect({
onChange,
value,
}: {
onChange: (value: string) => void
value: string
}) {
const { channels } = useCurrentGuild()
const textChannels = channels.filter((channel) => channel.type === 0)
return (
<Select onValueChange={onChange} defaultValue={value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select a channel" />
</SelectTrigger>
</FormControl>
<SelectContent>
{textChannels.map(({ id, name }) => (
<SelectItem key={id} value={id}>
#{name}
</SelectItem>
))}
</SelectContent>
</Select>
)
}
Loading

0 comments on commit 50ed262

Please sign in to comment.