Initial Release

This commit is contained in:
Tola Leng
2025-05-09 21:28:07 +07:00
commit 0c6cd18e6f
244 changed files with 50633 additions and 0 deletions
@@ -0,0 +1,95 @@
import React from "react";
import { Form } from "@/components/ui/form";
import { Button } from "@/components/ui/button";
import { Loader2 } from "lucide-react";
import { UseFormReturn } from "react-hook-form";
import UserProfilePictureField from "./UserProfilePictureField";
import UserTextField from "./UserTextField";
import UserToggleField from "./UserToggleField";
import { DialogFooter } from "@/components/ui/dialog";
interface AddUserFormProps {
form: UseFormReturn<any>;
onSubmit: (data: any) => void;
isSubmitting: boolean;
}
const AddUserForm = ({ form, onSubmit, isSubmitting }: AddUserFormProps) => {
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<UserProfilePictureField control={form.control} />
<div className="grid grid-cols-2 gap-4">
<UserTextField
control={form.control}
name="full_name"
label="Full Name"
placeholder="Enter full name"
/>
<UserTextField
control={form.control}
name="email"
label="Email"
placeholder="Enter email"
type="email"
/>
<UserTextField
control={form.control}
name="username"
label="Username"
placeholder="Enter username"
/>
<UserTextField
control={form.control}
name="role"
label="Role"
placeholder="Enter role (e.g. admin, user)"
/>
<UserTextField
control={form.control}
name="password"
label="Password"
placeholder="Enter password"
type="password"
/>
<UserTextField
control={form.control}
name="passwordConfirm"
label="Confirm Password"
placeholder="Confirm password"
type="password"
/>
</div>
<UserToggleField
control={form.control}
name="isActive"
label="Active Status"
description="User will be able to access the system"
/>
<DialogFooter className="pt-4">
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Creating...
</>
) : (
"Create User"
)}
</Button>
</DialogFooter>
</form>
</Form>
);
};
export default AddUserForm;
@@ -0,0 +1,76 @@
import React from "react";
import { FormField, FormItem, FormLabel, FormControl, FormMessage } from "@/components/ui/form";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Control } from "react-hook-form";
// Custom interface for local profile images
interface ProfileImage {
url: string;
label: string;
}
// Define local profile image paths - include all uploaded SVG images
const localProfileImages: ProfileImage[] = [
{ url: "/upload/profile/profile1.svg", label: "Profile 1" },
{ url: "/upload/profile/profile2.svg", label: "Profile 2" },
{ url: "/upload/profile/profile3.svg", label: "Profile 3" },
{ url: "/upload/profile/profile4.svg", label: "Profile 4" },
{ url: "/upload/profile/profile5.svg", label: "Profile 5" },
{ url: "/upload/profile/profile6.svg", label: "Profile 6" },
{ url: "/upload/profile/profile7.svg", label: "Profile 7" },
{ url: "/upload/profile/profile8.svg", label: "Profile 8" }
];
interface UserProfilePictureFieldProps {
control: Control<any>;
}
const UserProfilePictureField = ({ control }: UserProfilePictureFieldProps) => {
return (
<FormField
control={control}
name="avatar"
render={({ field }) => (
<FormItem>
<FormLabel>Profile Picture</FormLabel>
<RadioGroup
onValueChange={field.onChange}
value={field.value}
className="grid grid-cols-3 gap-4"
>
{localProfileImages.map((avatar) => (
<FormItem key={avatar.url} className="flex flex-col items-center justify-center space-y-1">
<FormControl>
<RadioGroupItem
value={avatar.url}
id={`new-${avatar.url}`}
className="sr-only"
/>
</FormControl>
<label
htmlFor={`new-${avatar.url}`}
className={`cursor-pointer rounded-md p-1 ${
field.value === avatar.url
? "ring-2 ring-primary ring-offset-2"
: ""
}`}
>
<Avatar className="h-16 w-16">
<AvatarImage src={avatar.url} alt={avatar.label} />
<AvatarFallback>?</AvatarFallback>
</Avatar>
</label>
<div className="text-xs text-center">{avatar.label}</div>
</FormItem>
))}
</RadioGroup>
<FormMessage />
</FormItem>
)}
/>
);
};
export default UserProfilePictureField;
@@ -0,0 +1,54 @@
import React from "react";
import { FormField, FormItem, FormLabel, FormControl, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Control } from "react-hook-form";
interface UserTextFieldProps {
control: Control<any>;
name: string;
label: string;
placeholder: string;
type?: string;
required?: boolean;
}
const UserTextField = ({
control,
name,
label,
placeholder,
type = "text",
required = false
}: UserTextFieldProps) => {
return (
<FormField
control={control}
name={name}
render={({ field }) => (
<FormItem>
<FormLabel>
{label}
{required && <span className="text-destructive ml-1">*</span>}
</FormLabel>
<FormControl>
<Input
type={type}
placeholder={placeholder}
{...field}
value={field.value || ''}
onChange={e => {
// Handle the value change properly
const value = e.target.value;
field.onChange(value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
);
};
export default UserTextField;
@@ -0,0 +1,39 @@
import React from "react";
import { FormField, FormItem, FormLabel, FormControl, FormMessage, FormDescription } from "@/components/ui/form";
import { Switch } from "@/components/ui/switch";
import { Control } from "react-hook-form";
interface UserToggleFieldProps {
control: Control<any>;
name: string;
label: string;
description: string;
}
const UserToggleField = ({ control, name, label, description }: UserToggleFieldProps) => {
return (
<FormField
control={control}
name={name}
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-3">
<div className="space-y-0.5">
<FormLabel>{label}</FormLabel>
<FormDescription>
{description}
</FormDescription>
</div>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
);
};
export default UserToggleField;
@@ -0,0 +1,5 @@
export { default as UserProfilePictureField } from './UserProfilePictureField';
export { default as UserTextField } from './UserTextField';
export { default as UserToggleField } from './UserToggleField';
export { default as AddUserForm } from './AddUserForm';