Skip to content

Commit

Permalink
Added user creation form.
Browse files Browse the repository at this point in the history
  • Loading branch information
shrihari-prakash committed Aug 20, 2024
1 parent 30551c8 commit 6932df4
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 29 deletions.
172 changes: 172 additions & 0 deletions src/components/features/user-editor/user-create.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { useContext, useState } from "react";
import {
Sheet,
SheetContent,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
import { useForm } from "react-hook-form";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { BiUserPlus } from "react-icons/bi";
import { Save } from "lucide-react";
import { camelCaseToWords } from "@/utils/string";
import { toast } from "sonner";
import axiosInstance from "@/service/axios";
import UsersContext, { UsersSearchResultsContext } from "@/context/users-context";

const UserCreate = () => {
const [open, setOpen] = useState(false);
const [submitting, setSubmitting] = useState(false);
const { setUsers } = useContext(UsersContext);
const { setUsersSearchResults } = useContext(UsersSearchResultsContext);

const formDefaults = {
username: "",
firstName: "",
lastName: "",
email: "",
password: "",
};

const form = useForm({ defaultValues: formDefaults });

async function onSubmit(formValues: any) {
setSubmitting(true);
console.log(formValues);
let promise;
try {
promise = axiosInstance.post("/user/admin-api/create", [formValues]);
toast.promise(promise, {
loading: "Creating user...",
success: "User created successfully!",
error: (data: any) => {
console.log(data);
const errors = data?.response?.data?.additionalInfo?.errors;
if (errors) {
return "Invalid " + camelCaseToWords(errors[0].path);
}
if (data?.response?.data?.additionalInfo?.existingUsers) {
return "User already exists!";
}
return "Failed to create user!";
},
});
await promise;
setUsers(() => []);
setUsersSearchResults(null);
} finally {
setSubmitting(false);
}
}

return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger>
<Button variant="outline" className="gap-1">
<BiUserPlus className="text-xl" /> Create User
</Button>
</SheetTrigger>
<SheetContent className="w-full md:!max-w-[550px] overflow-y-auto">
<SheetHeader>
<SheetTitle>Create user</SheetTitle>
</SheetHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
Must be atleast 8 characters long. Can include alphabets,
numbers and underscores.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="firstName"
render={({ field }) => (
<FormItem>
<FormLabel>First Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="lastName"
render={({ field }) => (
<FormItem>
<FormLabel>Last Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input type="password" {...field} />
</FormControl>
<FormDescription>
Must be atleast 8 characters long.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<SheetFooter className="flex-col sm:justify-center">
<Button type="submit" className="mb-2 md:mb-0" variant="outline">
<Save className="h-4 w-4 mr-2" />
{submitting ? "Saving..." : "Save Basic Info"}
</Button>
</SheetFooter>
</form>
</Form>
</SheetContent>
</Sheet>
);
};

export default UserCreate;
67 changes: 38 additions & 29 deletions src/components/features/user-list/user-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import UsersContext, {
UsersSearchResultsContext,
} from "@/context/users-context";
import { Badge } from "@/components/ui/badge";
import UserCreate from "../user-editor/user-create";

const UserList = function () {
const { me } = React.useContext(MeContext);
Expand Down Expand Up @@ -74,6 +75,7 @@ const UserList = function () {
const searchRef = React.useRef();

React.useEffect(() => {
console.log("UserList mounted", users);
if (!users.length) {
setLoading(true);
axiosInstance
Expand Down Expand Up @@ -116,7 +118,9 @@ const UserList = function () {
if (!query || query.length === 0) {
return setUsersSearchResults(null);
}
const response = await axiosInstance.post("/user/admin-api/search", { query });
const response = await axiosInstance.post("/user/admin-api/search", {
query,
});
setUsersSearchResults(response.data.data.results);
} finally {
setLoading(false);
Expand All @@ -138,7 +142,9 @@ const UserList = function () {

return (
<div className="w-full h-full p-4 md:p-8">
<TypographyH4 className="capitalize">Hello, {(me as User).firstName}</TypographyH4>
<TypographyH4 className="capitalize">
Hello, {(me as User).firstName}
</TypographyH4>
<div className="flex items-center py-4">
{isPermissionAllowed("delegated:profile:search") && (
<>
Expand All @@ -157,34 +163,37 @@ const UserList = function () {
</Button>
</>
)}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto">
Columns <ChevronDown className="ml-2 h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{table
.getAllColumns()
.filter((column) => column.getCanHide())
.map((column) => {
return (
<DropdownMenuCheckboxItem
key={column.id}
className="capitalize"
checked={column.getIsVisible()}
onCheckedChange={(value) =>
column.toggleVisibility(!!value)
}
>
{column.id}
</DropdownMenuCheckboxItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
<div className="flex justify-between items-center my-4 ml-auto gap-2">
<UserCreate />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto">
Columns <ChevronDown className="ml-2 h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{table
.getAllColumns()
.filter((column) => column.getCanHide())
.map((column) => {
return (
<DropdownMenuCheckboxItem
key={column.id}
className="capitalize"
checked={column.getIsVisible()}
onCheckedChange={(value) =>
column.toggleVisibility(!!value)
}
>
{column.id}
</DropdownMenuCheckboxItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
<div className="flex mb-4 font-medium">
<div className="flex font-medium mb-4">
Total users:{" "}
<Badge variant="secondary" className="ml-2 font-medium">
{totalUsers}
Expand Down

0 comments on commit 6932df4

Please sign in to comment.