Fix naming and add update to site provider?

This commit is contained in:
Owen Schwartz 2024-10-19 12:48:07 -04:00
parent edde7a247a
commit 474bc7997e
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD
10 changed files with 238 additions and 23 deletions

View file

@ -46,10 +46,10 @@ authenticated.put("/org/:orgId/site", verifyOrgAccess, site.createSite);
authenticated.get("/org/:orgId/sites", verifyOrgAccess, site.listSites); authenticated.get("/org/:orgId/sites", verifyOrgAccess, site.listSites);
authenticated.get("/org/:orgId/site/:niceId", verifyOrgAccess, site.getSite); authenticated.get("/org/:orgId/site/:niceId", verifyOrgAccess, site.getSite);
authenticated.get("/site/siteId/:siteId", verifySiteAccess, site.getSite); authenticated.get("/site/:siteId", verifySiteAccess, site.getSite);
authenticated.get("/site/siteId/:siteId/roles", verifySiteAccess, site.listSiteRoles); authenticated.get("/site/:siteId/roles", verifySiteAccess, site.listSiteRoles);
authenticated.post("/site/siteId/:siteId", verifySiteAccess, site.updateSite); authenticated.post("/site/:siteId", verifySiteAccess, site.updateSite);
authenticated.delete("/site/siteId/:siteId", verifySiteAccess, site.deleteSite); authenticated.delete("/site/:siteId", verifySiteAccess, site.deleteSite);
authenticated.put( authenticated.put(
"/org/:orgId/site/:siteId/resource", "/org/:orgId/site/:siteId/resource",

View file

@ -18,7 +18,7 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form" } from "@/components/ui/form"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { generateKeypair } from "./wireguard-config"; import { generateKeypair } from "./wireguardConfig";
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { api } from "@/api"; import { api } from "@/api";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";

View file

@ -0,0 +1,174 @@
"use client"
import Link from "next/link"
import { zodResolver } from "@hookform/resolvers/zod"
import { useFieldArray, useForm } from "react-hook-form"
import { z } from "zod"
import { cn } from "@/lib/utils"
import { toast } from "@/hooks/use-toast"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Textarea } from "@/components/ui/textarea"
import { useSiteContext } from "@app/hooks/useSiteContext"
import api from "@app/api"
const GeneralFormSchema = z.object({
name: z.string()
// email: z
// .string({
// required_error: "Please select an email to display.",
// })
// .email(),
// bio: z.string().max(160).min(4),
// urls: z
// .array(
// z.object({
// value: z.string().url({ message: "Please enter a valid URL." }),
// })
// )
// .optional(),
})
type GeneralFormValues = z.infer<typeof GeneralFormSchema>
export function GeneralForm() {
const { site, updateSite } = useSiteContext();
const form = useForm<GeneralFormValues>({
resolver: zodResolver(GeneralFormSchema),
defaultValues: {
name: site?.name
},
mode: "onChange",
})
// const { fields, append } = useFieldArray({
// name: "urls",
// control: form.control,
// })
async function onSubmit(data: GeneralFormValues) {
await updateSite({ name: data.name });
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
This is the display name of the site.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* <FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select a verified email to display" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="m@example.com">m@example.com</SelectItem>
<SelectItem value="m@google.com">m@google.com</SelectItem>
<SelectItem value="m@support.com">m@support.com</SelectItem>
</SelectContent>
</Select>
<FormDescription>
You can manage verified email addresses in your{" "}
<Link href="/examples/forms">email settings</Link>.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="bio"
render={({ field }) => (
<FormItem>
<FormLabel>Bio</FormLabel>
<FormControl>
<Textarea
placeholder="Tell us a little bit about yourself"
className="resize-none"
{...field}
/>
</FormControl>
<FormDescription>
You can <span>@mention</span> other users and organizations to
link to them.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<div>
{fields.map((field, index) => (
<FormField
control={form.control}
key={field.id}
name={`urls.${index}.value`}
render={({ field }) => (
<FormItem>
<FormLabel className={cn(index !== 0 && "sr-only")}>
URLs
</FormLabel>
<FormDescription className={cn(index !== 0 && "sr-only")}>
Add links to your website, blog, or social media profiles.
</FormDescription>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
))}
<Button
type="button"
variant="outline"
size="sm"
className="mt-2"
onClick={() => append({ value: "" })}
>
Add URL
</Button>
</div> */}
<Button type="submit">Update Site</Button>
</form>
</Form>
)
}

View file

@ -11,6 +11,8 @@ import { redirect } from "next/navigation";
import { authCookieHeader } from "@app/api/cookies"; import { authCookieHeader } from "@app/api/cookies";
import Link from "next/link"; import Link from "next/link";
import { ArrowLeft, ChevronLeft } from "lucide-react"; import { ArrowLeft, ChevronLeft } from "lucide-react";
import { useEffect, useState } from "react";
import { toast } from "@app/hooks/use-toast";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Forms", title: "Forms",
@ -46,6 +48,7 @@ export default async function SettingsLayout({
params, params,
}: SettingsLayoutProps) { }: SettingsLayoutProps) {
let site = null; let site = null;
if (params.niceId !== "create") { if (params.niceId !== "create") {
try { try {
const res = await internal.get<AxiosResponse<GetSiteResponse>>( const res = await internal.get<AxiosResponse<GetSiteResponse>>(

View file

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import { ProfileForm } from "@app/components/profile-form"; import { CreateSiteForm } from "./components/CreateSite";
import { CreateSiteForm } from "./components/create-site"; import { GeneralForm } from "./components/GeneralForm";
export default function SettingsProfilePage({ export default function SettingsProfilePage({
params, params,
@ -24,7 +24,7 @@ export default function SettingsProfilePage({
</div> </div>
<Separator /> <Separator />
{isCreateForm ? <CreateSiteForm /> : <ProfileForm />} {isCreateForm ? <CreateSiteForm /> : <GeneralForm />}
</div> </div>
); );
} }

View file

@ -1,4 +1,11 @@
import { GetSiteResponse } from "@server/routers/site/getSite"; import { GetSiteResponse } from "@server/routers/site/getSite";
import { createContext } from "react"; import { createContext } from "react";
export const SiteContext = createContext<GetSiteResponse | null>(null); interface SiteContextType {
site: GetSiteResponse | null;
updateSite: (updatedSite: Partial<GetSiteResponse>) => Promise<void>;
}
const SiteContext = createContext<SiteContextType | undefined>(undefined);
export default SiteContext;

View file

@ -1,7 +1,10 @@
import { SiteContext } from "@app/contexts/siteContext"; import SiteContext from "@app/contexts/siteContext";
import { useContext } from "react"; import { useContext } from "react";
export function useSiteContext() { export function useSiteContext() {
const site = useContext(SiteContext); const context = useContext(SiteContext);
return site; if (context === undefined) {
throw new Error('useSiteContext must be used within a SiteProvider');
}
return context;
} }

View file

@ -1,16 +1,44 @@
"use client"; "use client";
import { SiteContext } from "@app/contexts/siteContext"; import api from "@app/api";
import SiteContext from "@app/contexts/siteContext";
import { toast } from "@app/hooks/use-toast";
import { GetSiteResponse } from "@server/routers/site/getSite"; import { GetSiteResponse } from "@server/routers/site/getSite";
import { ReactNode } from "react"; import { AxiosResponse } from "axios";
import { useState } from "react";
type LandingProviderProps = { interface SiteProviderProps {
children: React.ReactNode;
site: GetSiteResponse | null; site: GetSiteResponse | null;
children: ReactNode; }
export function SiteProvider({ children, site: serverSite }: SiteProviderProps) {
const [site, setSite] = useState<GetSiteResponse | null>(serverSite);
const updateSite = async (updatedSite: Partial<GetSiteResponse>) => {
try {
if (!site) {
throw new Error("No site to update");
}
const res = await api.post<AxiosResponse<GetSiteResponse>>(
`site/${site.siteId}`,
updatedSite,
);
setSite(res.data.data);
toast({
title: "Site updated!",
});
} catch (error) {
console.error(error);
toast({
title: "Error updating site...",
})
}
}; };
export function SiteProvider({ site, children }: LandingProviderProps) {
return <SiteContext.Provider value={site}>{children}</SiteContext.Provider>; return <SiteContext.Provider value={{ site, updateSite }}>{children}</SiteContext.Provider>;
} }
export default SiteProvider; export default SiteProvider;