🔧 fix(PaginatorComponent): remove unused imports and replace lucide-react icons with IconComponent for better modularity and reusability
✨ feat(PaginatorComponent): add support for custom icons using IconComponent for better customization options 🔧 fix(UserManagementModal): remove unused imports and fix import order for better organization ✨ feat(UserManagementModal): add password confirmation validation and reset form on modal open for better user experience 🔧 fix(UserManagementModal): fix modal size to be full height for better visibility and usability ✨ feat(UserManagementModal): add form fields for username and password with validation for better user input handling 🔧 fix(UserManagementModal): fix form field labels and error messages for better clarity and user guidance ✨ feat(UserManagementModal): add form submission and confirmation handling for better user interaction and data management 🔧 fix(UserManagementModal): fix cancel button styling for better consistency and user experience 🔧 fix(baseModal): add missing size options to the size prop to support additional modal sizes ✨ feat(baseModal): add support for "small-h-full" and "medium-h-full" sizes to allow modals with smaller height and full width 🔧 fix(AdminPage): import missing IconComponent and ShadTooltip components ✨ feat(AdminPage): add functionality to handle editing and adding new users 🔧 fix(applies.css): add missing semicolon to .field-invalid and .label-invalid classes 🔧 fix(styleUtils.ts): import missing Pencil, ChevronsRight, and ChevronsLeft icons
This commit is contained in:
parent
26345cc9a6
commit
5009715835
7 changed files with 291 additions and 117 deletions
|
|
@ -1,9 +1,3 @@
|
||||||
import {
|
|
||||||
ChevronLeft,
|
|
||||||
ChevronRight,
|
|
||||||
ChevronsLeft,
|
|
||||||
ChevronsRight,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
|
|
@ -13,6 +7,7 @@ import {
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "../../components/ui/select";
|
} from "../../components/ui/select";
|
||||||
import { PaginatorComponentType } from "../../types/components";
|
import { PaginatorComponentType } from "../../types/components";
|
||||||
|
import IconComponent from "../genericIconComponent";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
|
||||||
export default function PaginatorComponent({
|
export default function PaginatorComponent({
|
||||||
|
|
@ -20,7 +15,7 @@ export default function PaginatorComponent({
|
||||||
pageIndex = 1,
|
pageIndex = 1,
|
||||||
rowsCount = [10, 20, 30],
|
rowsCount = [10, 20, 30],
|
||||||
totalRowsCount = 0,
|
totalRowsCount = 0,
|
||||||
paginate
|
paginate,
|
||||||
}: PaginatorComponentType) {
|
}: PaginatorComponentType) {
|
||||||
const [size, setPageSize] = useState(pageSize);
|
const [size, setPageSize] = useState(pageSize);
|
||||||
const [index, setPageIndex] = useState(pageIndex);
|
const [index, setPageIndex] = useState(pageIndex);
|
||||||
|
|
@ -68,7 +63,7 @@ export default function PaginatorComponent({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Go to first page</span>
|
<span className="sr-only">Go to first page</span>
|
||||||
<ChevronsLeft className="h-4 w-4" strokeWidth={1.5} />
|
<IconComponent name="ChevronsLeft" className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -86,7 +81,7 @@ export default function PaginatorComponent({
|
||||||
className="h-8 w-8 p-0"
|
className="h-8 w-8 p-0"
|
||||||
>
|
>
|
||||||
<span className="sr-only">Go to previous page</span>
|
<span className="sr-only">Go to previous page</span>
|
||||||
<ChevronLeft className="h-4 w-4" strokeWidth={1.5} />
|
<IconComponent name="ChevronLeft" className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -102,7 +97,7 @@ export default function PaginatorComponent({
|
||||||
className="h-8 w-8 p-0"
|
className="h-8 w-8 p-0"
|
||||||
>
|
>
|
||||||
<span className="sr-only">Go to next page</span>
|
<span className="sr-only">Go to next page</span>
|
||||||
<ChevronRight className="h-4 w-4" strokeWidth={1.5} />
|
<IconComponent name="ChevronRight" className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|
@ -113,7 +108,7 @@ export default function PaginatorComponent({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Go to last page</span>
|
<span className="sr-only">Go to last page</span>
|
||||||
<ChevronsRight className="h-4 w-4" strokeWidth={1.5} />
|
<IconComponent name="ChevronsRight" className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,5 @@ export default function IconComponent({
|
||||||
iconColor,
|
iconColor,
|
||||||
}: IconComponentProps): JSX.Element {
|
}: IconComponentProps): JSX.Element {
|
||||||
const TargetIcon = nodeIconsLucide[name] ?? nodeIconsLucide["unknown"];
|
const TargetIcon = nodeIconsLucide[name] ?? nodeIconsLucide["unknown"];
|
||||||
return <TargetIcon className={className} style={{ color: iconColor }} />;
|
return <TargetIcon strokeWidth={1.5} className={className} style={{ color: iconColor }} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { useState } from "react";
|
import * as Form from "@radix-ui/react-form";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { ConfirmationModalType, UserManagementType } from "../../types/components";
|
import { UserManagementType } from "../../types/components";
|
||||||
import { nodeIconsLucide } from "../../utils/styleUtils";
|
import { nodeIconsLucide } from "../../utils/styleUtils";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
import * as Form from '@radix-ui/react-form';
|
|
||||||
|
|
||||||
export default function UserManagementModal({
|
export default function UserManagementModal({
|
||||||
title,
|
title,
|
||||||
|
|
@ -19,8 +19,25 @@ export default function UserManagementModal({
|
||||||
const Icon: any = nodeIconsLucide[icon];
|
const Icon: any = nodeIconsLucide[icon];
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const [password, setPassword] = useState(data?.password ?? "");
|
||||||
|
const [username, setUserName] = useState(data?.user ?? "");
|
||||||
|
const [confirmPassword, setConfirmPassword] = useState(data?.password ?? "");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
}, [data, open]);
|
||||||
|
|
||||||
|
function resetForm() {
|
||||||
|
setPassword("");
|
||||||
|
setUserName("");
|
||||||
|
setConfirmPassword("");
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal size="medium" open={open} setOpen={setOpen}>
|
<BaseModal size="medium-h-full" open={open} setOpen={setOpen}>
|
||||||
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
||||||
<BaseModal.Header description={titleHeader}>
|
<BaseModal.Header description={titleHeader}>
|
||||||
<span className="pr-2">{title}</span>
|
<span className="pr-2">{title}</span>
|
||||||
|
|
@ -31,64 +48,190 @@ export default function UserManagementModal({
|
||||||
/>
|
/>
|
||||||
</BaseModal.Header>
|
</BaseModal.Header>
|
||||||
<BaseModal.Content>
|
<BaseModal.Content>
|
||||||
|
<Form.Root
|
||||||
|
onSubmit={(event) => {
|
||||||
|
if (password !== confirmPassword) {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = Object.fromEntries(new FormData(event.currentTarget));
|
||||||
|
resetForm();
|
||||||
|
onConfirm(index ?? -1, data);
|
||||||
|
setOpen(false);
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="grid gap-5">
|
||||||
|
<Form.Field name="username">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "baseline",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Label className="data-[invalid]:label-invalid">
|
||||||
|
Username{" "}
|
||||||
|
<span className="font-medium text-destructive">*</span>
|
||||||
|
</Form.Label>
|
||||||
|
</div>
|
||||||
|
<Form.Control asChild>
|
||||||
|
<input
|
||||||
|
onChange={(input) => {
|
||||||
|
setUserName(input.target.value);
|
||||||
|
}}
|
||||||
|
value={username}
|
||||||
|
className="primary-input"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Form.Control>
|
||||||
|
<Form.Message match="valueMissing" className="field-invalid">
|
||||||
|
Please enter your username
|
||||||
|
</Form.Message>
|
||||||
|
</Form.Field>
|
||||||
|
|
||||||
<Form.Root className="FormRoot">
|
<div className="flex flex-row">
|
||||||
<Form.Field className="FormField" name="email">
|
<div className="mr-3 basis-1/2">
|
||||||
<div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
|
<Form.Field
|
||||||
<Form.Label className="FormLabel">Email</Form.Label>
|
name="password"
|
||||||
<Form.Message className="FormMessage" match="valueMissing">
|
serverInvalid={password != confirmPassword}
|
||||||
Please enter your email
|
>
|
||||||
</Form.Message>
|
<div
|
||||||
<Form.Message className="FormMessage" match="typeMismatch">
|
style={{
|
||||||
Please provide a valid email
|
display: "flex",
|
||||||
</Form.Message>
|
alignItems: "baseline",
|
||||||
</div>
|
justifyContent: "space-between",
|
||||||
<Form.Control asChild>
|
}}
|
||||||
<input className="Input" type="email" required />
|
>
|
||||||
</Form.Control>
|
<Form.Label className="data-[invalid]:label-invalid">
|
||||||
</Form.Field>
|
Password{" "}
|
||||||
<Form.Field className="FormField" name="question">
|
<span className="font-medium text-destructive">*</span>
|
||||||
<div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
|
</Form.Label>
|
||||||
<Form.Label className="FormLabel">Question</Form.Label>
|
</div>
|
||||||
<Form.Message className="FormMessage" match="valueMissing">
|
<Form.Control asChild>
|
||||||
Please enter a question
|
<input
|
||||||
</Form.Message>
|
onChange={(input) => {
|
||||||
</div>
|
setPassword(input.target.value);
|
||||||
<Form.Control asChild>
|
}}
|
||||||
<textarea className="Textarea" required />
|
value={password}
|
||||||
</Form.Control>
|
className="primary-input"
|
||||||
</Form.Field>
|
required
|
||||||
<Form.Submit asChild>
|
/>
|
||||||
<button className="Button" style={{ marginTop: 10 }}>
|
</Form.Control>
|
||||||
Post question
|
<Form.Message className="field-invalid" match="valueMissing">
|
||||||
</button>
|
Please enter a password
|
||||||
</Form.Submit>
|
</Form.Message>
|
||||||
</Form.Root>
|
|
||||||
|
|
||||||
|
{password != confirmPassword && (
|
||||||
|
<Form.Message className="field-invalid">
|
||||||
|
Passwords do not match
|
||||||
|
</Form.Message>
|
||||||
|
)}
|
||||||
|
</Form.Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="basis-1/2">
|
||||||
|
<Form.Field
|
||||||
|
name="confirmpassword"
|
||||||
|
serverInvalid={password != confirmPassword}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "baseline",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Label className="data-[invalid]:label-invalid">
|
||||||
|
Confirm password{" "}
|
||||||
|
<span className="font-medium text-destructive">*</span>
|
||||||
|
</Form.Label>
|
||||||
|
</div>
|
||||||
|
<Form.Control asChild>
|
||||||
|
<input
|
||||||
|
onChange={(input) => {
|
||||||
|
setConfirmPassword(input.target.value);
|
||||||
|
}}
|
||||||
|
value={confirmPassword}
|
||||||
|
className="primary-input"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Form.Control>
|
||||||
|
<Form.Message className="field-invalid" match="valueMissing">
|
||||||
|
Please confirm your password
|
||||||
|
</Form.Message>
|
||||||
|
</Form.Field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<Form.Field name="email">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "baseline",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Label className="data-[invalid]:label-invalid">
|
||||||
|
Email <span className="font-medium text-destructive">*</span>
|
||||||
|
</Form.Label>
|
||||||
|
<Form.Message className="field-invalid" match="valueMissing">
|
||||||
|
Please enter your email
|
||||||
|
</Form.Message>
|
||||||
|
<Form.Message className="field-invalid" match="typeMismatch">
|
||||||
|
Please provide a valid email
|
||||||
|
</Form.Message>
|
||||||
|
</div>
|
||||||
|
<Form.Control asChild>
|
||||||
|
<input className="primary-input" type="email" required />
|
||||||
|
</Form.Control>
|
||||||
|
</Form.Field> */}
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<Form.Field name="birth">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "baseline",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Label className="data-[invalid]:label-invalid">
|
||||||
|
Date of birth{" "}
|
||||||
|
<span className="font-medium text-destructive">*</span>
|
||||||
|
</Form.Label>
|
||||||
|
<Form.Message className="field-invalid" match="valueMissing">
|
||||||
|
Please enter your date of birth
|
||||||
|
</Form.Message>
|
||||||
|
</div>
|
||||||
|
<Form.Control asChild>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
className="primary-input"
|
||||||
|
required
|
||||||
|
max={new Date().toISOString().split("T")[0]}
|
||||||
|
/>
|
||||||
|
</Form.Control>
|
||||||
|
</Form.Field> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="float-right">
|
||||||
|
<Form.Submit asChild>
|
||||||
|
<Button className="mr-3 mt-8">{confirmationText}</Button>
|
||||||
|
</Form.Submit>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{cancelText}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form.Root>
|
||||||
</BaseModal.Content>
|
</BaseModal.Content>
|
||||||
|
|
||||||
<BaseModal.Footer>
|
|
||||||
<Button
|
|
||||||
className="ml-3"
|
|
||||||
onClick={() => {
|
|
||||||
setOpen(false);
|
|
||||||
onConfirm(index, data);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{confirmationText}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
onClick={() => {
|
|
||||||
setOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{cancelText}
|
|
||||||
</Button>
|
|
||||||
</BaseModal.Footer>
|
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ interface BaseModalProps {
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
setOpen?: (open: boolean) => void;
|
setOpen?: (open: boolean) => void;
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
size?: "x-small" | "smaller" | "small" | "medium" | "large" | "large-h-full";
|
size?: "x-small" | "smaller" | "small" | "medium" | "large" | "large-h-full" | "small-h-full" | "medium-h-full";
|
||||||
}
|
}
|
||||||
function BaseModal({
|
function BaseModal({
|
||||||
open,
|
open,
|
||||||
|
|
@ -85,10 +85,16 @@ function BaseModal({
|
||||||
minWidth = "min-w-[40vw]";
|
minWidth = "min-w-[40vw]";
|
||||||
height = "h-[40vh]";
|
height = "h-[40vh]";
|
||||||
break;
|
break;
|
||||||
|
case "small-h-full":
|
||||||
|
minWidth = "min-w-[40vw]";
|
||||||
|
break;
|
||||||
case "medium":
|
case "medium":
|
||||||
minWidth = "min-w-[60vw]";
|
minWidth = "min-w-[60vw]";
|
||||||
height = "h-[60vh]";
|
height = "h-[60vh]";
|
||||||
break;
|
break;
|
||||||
|
case "medium-h-full":
|
||||||
|
minWidth = "min-w-[60vw]";
|
||||||
|
break;
|
||||||
case "large":
|
case "large":
|
||||||
minWidth = "min-w-[80vw]";
|
minWidth = "min-w-[80vw]";
|
||||||
height = "h-[80vh]";
|
height = "h-[80vh]";
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import _ from "lodash";
|
||||||
import { Pencil, Trash2, X } from "lucide-react";
|
import { Pencil, Trash2, X } from "lucide-react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import PaginatorComponent from "../../components/PaginatorComponent";
|
import PaginatorComponent from "../../components/PaginatorComponent";
|
||||||
|
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Input } from "../../components/ui/input";
|
import { Input } from "../../components/ui/input";
|
||||||
import {
|
import {
|
||||||
|
|
@ -14,6 +15,7 @@ import {
|
||||||
} from "../../components/ui/table";
|
} from "../../components/ui/table";
|
||||||
import ConfirmationModal from "../../modals/ConfirmationModal";
|
import ConfirmationModal from "../../modals/ConfirmationModal";
|
||||||
import UserManagementModal from "../../modals/UserManagementModal";
|
import UserManagementModal from "../../modals/UserManagementModal";
|
||||||
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
|
|
||||||
export default function AdminPage() {
|
export default function AdminPage() {
|
||||||
const [inputValue, setInputValue] = useState("");
|
const [inputValue, setInputValue] = useState("");
|
||||||
|
|
@ -223,7 +225,27 @@ export default function AdminPage() {
|
||||||
resetFilter();
|
resetFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEditUser(index) {}
|
function handleEditUser(index, user) {
|
||||||
|
const newUser = _.cloneDeepWith(userList.current);
|
||||||
|
newUser[index].password = user.password;
|
||||||
|
newUser[index].user = user.username;
|
||||||
|
userList.current = newUser;
|
||||||
|
resetFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleNewUser(user) {
|
||||||
|
const newUser = {
|
||||||
|
user: user.username,
|
||||||
|
email: generateRandomString(50) + "@example.com",
|
||||||
|
password: user.password,
|
||||||
|
register_date: generateRandomDate(),
|
||||||
|
};
|
||||||
|
|
||||||
|
userList.current.unshift(newUser);
|
||||||
|
console.log(userList.current);
|
||||||
|
|
||||||
|
resetFilter();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -274,32 +296,29 @@ export default function AdminPage() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<UserManagementModal
|
<UserManagementModal
|
||||||
title="New User"
|
title="New User"
|
||||||
titleHeader={"Add a new user"}
|
titleHeader={"Add a new user"}
|
||||||
cancelText="Cancel"
|
cancelText="Cancel"
|
||||||
confirmationText="Save"
|
confirmationText="Save"
|
||||||
icon={"UserPlus2"}
|
icon={"UserPlus2"}
|
||||||
index={index}
|
onConfirm={(index, user) => {
|
||||||
onConfirm={(index, user) => {
|
handleNewUser(user);
|
||||||
handleDeleteUser(index);
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<Button>New User</Button>
|
||||||
<Button>New User</Button>
|
</UserManagementModal>
|
||||||
</UserManagementModal>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="overflow-scroll overflow-x-hidden rounded-md border-2 bg-muted
|
className="overflow-scroll overflow-x-hidden rounded-md border-2 bg-muted
|
||||||
custom-scroll min-[320px]:h-[20rem] md:h-[25rem] xl:h-[25rem] 2xl:h-[30rem]"
|
custom-scroll min-[320px]:h-[20rem] md:h-[25rem] xl:h-[26rem] 2xl:h-[30rem]"
|
||||||
>
|
>
|
||||||
<Table className="table-fixed bg-muted outline-1 ">
|
<Table className="table-fixed bg-muted outline-1 ">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableHead className="h-10">User</TableHead>
|
<TableHead className="h-10">User</TableHead>
|
||||||
<TableHead className="h-10">E-mail</TableHead>
|
<TableHead className="h-10">Password</TableHead>
|
||||||
<TableHead className="h-10">Register Date</TableHead>
|
|
||||||
<TableHead className="h-10 w-[100px] text-right"></TableHead>
|
<TableHead className="h-10 w-[100px] text-right"></TableHead>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
|
|
@ -310,13 +329,29 @@ export default function AdminPage() {
|
||||||
{user.user}
|
{user.user}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="truncate py-2">
|
<TableCell className="truncate py-2">
|
||||||
{user.email}
|
{user.password}
|
||||||
</TableCell>
|
|
||||||
<TableCell className="py-2">
|
|
||||||
{user.register_date.toString()}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="flex w-[100px] py-2 text-right">
|
<TableCell className="flex w-[100px] py-2 text-right">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
<UserManagementModal
|
||||||
|
title="Edit"
|
||||||
|
titleHeader={`${user.user}`}
|
||||||
|
cancelText="Cancel"
|
||||||
|
confirmationText="Edit"
|
||||||
|
icon={"UserPlus2"}
|
||||||
|
data={user}
|
||||||
|
index={index}
|
||||||
|
onConfirm={(index, user) => {
|
||||||
|
handleEditUser(index, user);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ShadTooltip content="Edit" side="top">
|
||||||
|
<IconComponent name="Pencil"
|
||||||
|
className="h-4 w-4 cursor-pointer"
|
||||||
|
/>
|
||||||
|
</ShadTooltip>
|
||||||
|
</UserManagementModal>
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
title="Delete"
|
title="Delete"
|
||||||
titleHeader="Delete User"
|
titleHeader="Delete User"
|
||||||
|
|
@ -331,31 +366,12 @@ export default function AdminPage() {
|
||||||
handleDeleteUser(index);
|
handleDeleteUser(index);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Trash2
|
<ShadTooltip content="Delete" side="top">
|
||||||
className="mr-2 h-4 w-4 cursor-pointer"
|
<IconComponent name="Trash2"
|
||||||
strokeWidth={1.5}
|
className="ml-2 h-4 w-4 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
|
</ShadTooltip>
|
||||||
</ConfirmationModal>
|
</ConfirmationModal>
|
||||||
<UserManagementModal
|
|
||||||
title="Edit"
|
|
||||||
titleHeader={`${user.user}`}
|
|
||||||
cancelText="Cancel"
|
|
||||||
confirmationText="Edit"
|
|
||||||
icon={"UserPlus2"}
|
|
||||||
data={user}
|
|
||||||
index={index}
|
|
||||||
onConfirm={(index, user) => {
|
|
||||||
handleDeleteUser(index);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Pencil
|
|
||||||
className="h-4 w-4 cursor-pointer"
|
|
||||||
onClick={() => {
|
|
||||||
handleEditUser(index);
|
|
||||||
}}
|
|
||||||
strokeWidth={1.5}
|
|
||||||
/>
|
|
||||||
</UserManagementModal>
|
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
|
||||||
|
|
@ -1019,4 +1019,12 @@
|
||||||
.chat-message-highlight {
|
.chat-message-highlight {
|
||||||
@apply rounded-md bg-indigo-100 px-0.5 dark:bg-indigo-900;
|
@apply rounded-md bg-indigo-100 px-0.5 dark:bg-indigo-900;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field-invalid{
|
||||||
|
@apply font-medium text-[0.8rem] text-destructive absolute
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-invalid{
|
||||||
|
@apply text-destructive
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,9 @@ import {
|
||||||
X,
|
X,
|
||||||
XCircle,
|
XCircle,
|
||||||
Zap,
|
Zap,
|
||||||
|
Pencil,
|
||||||
|
ChevronsRight,
|
||||||
|
ChevronsLeft
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { AirbyteIcon } from "../icons/Airbyte";
|
import { AirbyteIcon } from "../icons/Airbyte";
|
||||||
import { AnthropicIcon } from "../icons/Anthropic";
|
import { AnthropicIcon } from "../icons/Anthropic";
|
||||||
|
|
@ -278,5 +281,8 @@ export const nodeIconsLucide = {
|
||||||
MessageSquare,
|
MessageSquare,
|
||||||
MoreHorizontal,
|
MoreHorizontal,
|
||||||
UserMinus2,
|
UserMinus2,
|
||||||
UserPlus2
|
UserPlus2,
|
||||||
|
Pencil,
|
||||||
|
ChevronsRight,
|
||||||
|
ChevronsLeft
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue