Browse Source

Fix naming and add update to site provider?

Owen Schwartz 8 months ago
parent
commit
474bc7997e

+ 4 - 4
server/routers/external.ts

@@ -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/:siteId/roles", verifySiteAccess, site.listSiteRoles);
-authenticated.post("/site/siteId/:siteId", verifySiteAccess, site.updateSite);
-authenticated.delete("/site/siteId/:siteId", verifySiteAccess, site.deleteSite);
+authenticated.get("/site/:siteId", verifySiteAccess, site.getSite);
+authenticated.get("/site/:siteId/roles", verifySiteAccess, site.listSiteRoles);
+authenticated.post("/site/:siteId", verifySiteAccess, site.updateSite);
+authenticated.delete("/site/:siteId", verifySiteAccess, site.deleteSite);
 
 
 authenticated.put(
 authenticated.put(
     "/org/:orgId/site/:siteId/resource",
     "/org/:orgId/site/:siteId/resource",

+ 1 - 1
src/app/[orgId]/sites/[niceId]/components/create-site.tsx → src/app/[orgId]/sites/[niceId]/components/CreateSite.tsx

@@ -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";

+ 174 - 0
src/app/[orgId]/sites/[niceId]/components/GeneralForm.tsx

@@ -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>
+    )
+}

+ 0 - 0
src/app/[orgId]/sites/[niceId]/components/newt-config.tsx → src/app/[orgId]/sites/[niceId]/components/NewtConfig.tsx


+ 0 - 0
src/app/[orgId]/sites/[niceId]/components/wireguard-config.ts → src/app/[orgId]/sites/[niceId]/components/wireguardConfig.ts


+ 4 - 1
src/app/[orgId]/sites/[niceId]/layout.tsx

@@ -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>>(
@@ -96,7 +99,7 @@ export default async function SettingsLayout({
                         {params.niceId == "create"
                         {params.niceId == "create"
                             ? "Create a new site"
                             ? "Create a new site"
                             : "Configure the settings on your site: " +
                             : "Configure the settings on your site: " +
-                                  site?.name || ""}
+                            site?.name || ""}
                         .
                         .
                     </p>
                     </p>
                 </div>
                 </div>

+ 3 - 3
src/app/[orgId]/sites/[niceId]/page.tsx

@@ -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/create-site";
+import { CreateSiteForm } from "./components/CreateSite";
+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>
     );
     );
 }
 }

+ 8 - 1
src/contexts/siteContext.ts

@@ -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;

+ 7 - 4
src/hooks/useSiteContext.ts

@@ -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);
-    return site;
-}
+    const context = useContext(SiteContext);
+    if (context === undefined) {
+        throw new Error('useSiteContext must be used within a SiteProvider');
+    }
+    return context;
+}

+ 36 - 8
src/providers/SiteProvider.tsx

@@ -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;