| | import * as React from "react" |
| | import { buttonVariants } from "@/components/ui/button" |
| | import { |
| | Sheet, |
| | SheetContent, |
| | SheetDescription, |
| | SheetHeader, |
| | SheetTitle, |
| | SheetTrigger, |
| | } from "@/components/ui/sheet" |
| | import { |
| | Form, |
| | FormControl, |
| | FormField, |
| | FormItem, |
| | FormLabel, |
| | } from "@/components/ui/form" |
| | import { Button } from "@/components/ui/button" |
| | import { cn } from "@/lib/utils" |
| | import { LoaderCircleIcon, UsersIcon } from "lucide-react" |
| | import { set, useForm } from "react-hook-form" |
| | import { zodResolver } from "@hookform/resolvers/zod" |
| | import { z } from "zod" |
| | import { Switch } from "../ui/switch" |
| | import { useAppDispatch, useAppSelector } from "@/common/hooks" |
| | import { Input } from "../ui/input" |
| | import { setTrulienceSettings } from "@/store/reducers/global" |
| | import { toast } from "sonner" |
| |
|
| | export function TrulienceCfgSheet() { |
| | const dispatch = useAppDispatch() |
| | const trulienceSettings = useAppSelector((state) => state.global.trulienceSettings) |
| | return ( |
| | <Sheet> |
| | <SheetTrigger |
| | className={cn( |
| | buttonVariants({ variant: "outline", size: "icon" }), |
| | "bg-transparent" |
| | )} |
| | > |
| | <UsersIcon /> |
| | </SheetTrigger> |
| | <SheetContent className="w-[400px] overflow-y-auto sm:w-[540px]"> |
| | <SheetHeader> |
| | <SheetTitle>Trulience Avatar</SheetTitle> |
| | <SheetDescription> |
| | You can configure the Trulience Avatar settings here. This will give you a nice avatar for your chat. |
| | </SheetDescription> |
| | </SheetHeader> |
| | |
| | <div className="my-4"> |
| | <TrulienceCfgForm |
| | initialData={{ |
| | enable_trulience_avatar: trulienceSettings.enabled, |
| | trulience_avatar_id: trulienceSettings.avatarId, |
| | trulience_avatar_token: trulienceSettings.avatarToken, |
| | trulience_large_window: trulienceSettings.avatarDesktopLargeWindow, |
| | trulience_sdk_url: trulienceSettings.trulienceSDK, |
| | trulience_animation_url: trulienceSettings.animationURL, |
| | }} |
| | onUpdate={async (data) => { |
| | if (data.enable_trulience_avatar === true) { |
| | if (!data.trulience_avatar_id) { |
| | toast.error("Trulience Settings", { |
| | description: `Please provide Trulience Avatar ID`, |
| | }) |
| | return |
| | } |
| | } |
| | dispatch(setTrulienceSettings({ |
| | enabled: data.enable_trulience_avatar as boolean, |
| | avatarId: data.trulience_avatar_id as string, |
| | avatarToken: data.trulience_avatar_token as string, |
| | avatarDesktopLargeWindow: data.trulience_large_window as boolean, |
| | trulienceSDK: data.trulience_sdk_url as string, |
| | animationURL: data.trulience_animation_url as string, |
| | })) |
| | toast.success("Trulience Settings", { |
| | description: `Settings updated successfully`, |
| | }) |
| | }} |
| | /> |
| | </div> |
| | </SheetContent> |
| | </Sheet> |
| | ); |
| | } |
| |
|
| | const TrulienceCfgForm = ({ |
| | initialData, |
| | onUpdate, |
| | }: { |
| | initialData: Record<string, string | boolean | null | undefined>; |
| | onUpdate: (data: Record<string, string | boolean | null>) => void; |
| | }) => { |
| | const formSchema = z.record(z.string(), |
| | z.union([z.string(), z.boolean(), z.null()])); |
| | const form = useForm<z.infer<typeof formSchema>>({ |
| | resolver: zodResolver(formSchema), |
| | defaultValues: initialData, |
| | }); |
| | const { watch } = form; |
| | |
| | const enableTrulienceAvatar = watch("enable_trulience_avatar"); |
| |
|
| | const onSubmit = (data: z.infer<typeof formSchema>) => { |
| | onUpdate(data); |
| | }; |
| | return ( |
| | <Form {...form}> |
| | <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6"> |
| | <FormField |
| | key={"enable_trulience_avatar"} |
| | control={form.control} |
| | name={"enable_trulience_avatar"} |
| | render={({ field }) => ( |
| | <FormItem> |
| | <FormLabel>Enable Trulience Avatar</FormLabel> |
| | <div className="flex justify-between items-center"> |
| | <FormControl> |
| | <div className="flex items-center space-x-2"> |
| | <Switch |
| | checked={field.value === true} |
| | onCheckedChange={field.onChange} |
| | /> |
| | </div> |
| | </FormControl> |
| | </div> |
| | </FormItem> |
| | )} |
| | /> |
| | { |
| | enableTrulienceAvatar && ( |
| | <> |
| | <FormField |
| | key={"trulience_avatar_id"} |
| | control={form.control} |
| | name={"trulience_avatar_id"} |
| | render={({ field }) => ( |
| | <FormItem> |
| | <FormLabel>Trulience Avatar ID</FormLabel> |
| | <div className="flex justify-between items-center"> |
| | <FormControl> |
| | <Input |
| | {...field} |
| | value={ |
| | field.value === null || field.value === undefined |
| | ? "" |
| | : field.value.toString() |
| | } |
| | type={"text"} |
| | /> |
| | </FormControl> |
| | </div> |
| | </FormItem> |
| | )} |
| | /> |
| | <FormField |
| | key={"trulience_avatar_token"} |
| | control={form.control} |
| | name={"trulience_avatar_token"} |
| | render={({ field }) => ( |
| | <FormItem> |
| | <FormLabel>Trulience Avatar Token</FormLabel> |
| | <div className="flex justify-between items-center"> |
| | <FormControl> |
| | <Input |
| | {...field} |
| | value={ |
| | field.value === null || field.value === undefined |
| | ? "" |
| | : field.value.toString() |
| | } |
| | type={"text"} |
| | /> |
| | </FormControl> |
| | </div> |
| | </FormItem> |
| | )} |
| | /> |
| | <FormField |
| | key={"trulience_large_window"} |
| | control={form.control} |
| | name={"trulience_large_window"} |
| | render={({ field }) => ( |
| | <FormItem> |
| | <FormLabel>Trulience Large Window</FormLabel> |
| | <div className="flex justify-between items-center"> |
| | <FormControl> |
| | <div className="flex items-center space-x-2"> |
| | <Switch |
| | checked={field.value === true} |
| | onCheckedChange={field.onChange} |
| | /> |
| | </div> |
| | </FormControl> |
| | </div> |
| | </FormItem> |
| | )} |
| | /> |
| | <FormField |
| | key={"trulience_sdk_url"} |
| | control={form.control} |
| | name={"trulience_sdk_url"} |
| | render={({ field }) => ( |
| | <FormItem> |
| | <FormLabel>Trulience SDK URL</FormLabel> |
| | <div className="flex justify-between items-center"> |
| | <FormControl> |
| | <Input |
| | {...field} |
| | value={ |
| | field.value === null || field.value === undefined |
| | ? "" |
| | : field.value.toString() |
| | } |
| | type={"text"} |
| | /> |
| | </FormControl> |
| | </div> |
| | </FormItem> |
| | )} |
| | /> |
| | <FormField |
| | key={"trulience_animation_url"} |
| | control={form.control} |
| | name={"trulience_animation_url"} |
| | render={({ field }) => ( |
| | <FormItem> |
| | <FormLabel>Trulience Animation URL</FormLabel> |
| | <div className="flex justify-between items-center"> |
| | <FormControl> |
| | <Input |
| | {...field} |
| | value={ |
| | field.value === null || field.value === undefined |
| | ? "" |
| | : field.value.toString() |
| | } |
| | type={"text"} |
| | /> |
| | </FormControl> |
| | </div> |
| | </FormItem> |
| | )} |
| | /> |
| | </> |
| | ) |
| | } |
| | <Button type="submit" disabled={form.formState.isSubmitting}> |
| | {form.formState.isSubmitting ? ( |
| | <> |
| | <LoaderCircleIcon className="h-4 w-4 animate-spin" /> |
| | <span>Saving...</span> |
| | </> |
| | ) : ( |
| | "Save changes" |
| | )} |
| | </Button> |
| | </form> |
| | </Form> |
| | ); |
| | }; |
| |
|