feat(auth): admin user updates added
if a password change happens then an email will be sent to the user.
This commit is contained in:
43
frontend/src/components/admin/user/UserPage.tsx
Normal file
43
frontend/src/components/admin/user/UserPage.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { getUsers } from "@/utils/querys/admin/users";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import UserCard from "./components/UserCard";
|
||||
|
||||
export default function UserPage() {
|
||||
const { data, isError, error, isLoading } = useQuery(getUsers());
|
||||
|
||||
if (isLoading) return <div className="m-auto">Loading users...</div>;
|
||||
|
||||
if (isError)
|
||||
return (
|
||||
<div className="m-auto">
|
||||
There was an error getting the users.... {JSON.stringify(error)}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="m-2 w-dvw">
|
||||
<Accordion type="single" collapsible>
|
||||
{data.map((u: any) => {
|
||||
return (
|
||||
<AccordionItem key={u.user_id} value={u.user_id}>
|
||||
<AccordionTrigger>
|
||||
<span>{u.username}</span>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div>
|
||||
<UserCard user={u} />
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
);
|
||||
})}
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
183
frontend/src/components/admin/user/components/UserCard.tsx
Normal file
183
frontend/src/components/admin/user/components/UserCard.tsx
Normal file
@@ -0,0 +1,183 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { userFormOptions } from "@/utils/formStuff/options/userformOptions";
|
||||
import { generatePassword } from "@/utils/passwordGen";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function UserCard(data: any) {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const form = useForm({
|
||||
...userFormOptions(data.user),
|
||||
onSubmit: async ({ value }) => {
|
||||
// Do something with form data
|
||||
|
||||
const userData = { ...value, user_id: data.user.user_id };
|
||||
|
||||
try {
|
||||
const res = await axios.patch(
|
||||
"/api/auth/updateuser",
|
||||
userData,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
form.reset();
|
||||
} else {
|
||||
res.data.message;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="username"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 3
|
||||
? undefined
|
||||
: "Username must be longer than 3 letters",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="username">Username</Label>
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="email"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 3
|
||||
? undefined
|
||||
: "You must enter a correct ",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="email">Email</Label>
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<form.Field
|
||||
name="password"
|
||||
validators={{
|
||||
onChangeAsyncDebounceMs: 500,
|
||||
onChangeAsync: ({ value }) => {
|
||||
if (
|
||||
window.location.pathname.includes("/users") &&
|
||||
value.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (value.length < 4) {
|
||||
return "Password must be at least 4 characters long.";
|
||||
}
|
||||
|
||||
if (!/[A-Z]/.test(value)) {
|
||||
return "Password must contain at least one uppercase letter.";
|
||||
}
|
||||
|
||||
if (!/[a-z]/.test(value)) {
|
||||
return "Password must contain at least one lower case letter.";
|
||||
}
|
||||
|
||||
if (!/[0-9]/.test(value)) {
|
||||
return "Password must contain at least one number.";
|
||||
}
|
||||
|
||||
if (
|
||||
!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(
|
||||
value
|
||||
)
|
||||
) {
|
||||
return "Password must contain at least one special character.";
|
||||
}
|
||||
},
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="password">
|
||||
Change Password
|
||||
</Label>
|
||||
<div className="mt-2 flex flex-row">
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="ml-2"
|
||||
onClick={() =>
|
||||
field.handleChange(
|
||||
generatePassword(8)
|
||||
)
|
||||
}
|
||||
>
|
||||
Random password
|
||||
</Button>
|
||||
</div>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
<div>
|
||||
<Button onClick={form.handleSubmit}>Save</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user