Parcourir la source

update

create_edit_user
MSI\derek il y a 2 mois
Parent
révision
5c50e85198
5 fichiers modifiés avec 202 ajouts et 0 suppressions
  1. +47
    -0
      src/app/(main)/user/page.tsx
  2. +95
    -0
      src/components/UserSearch/UserSearch.tsx
  3. +40
    -0
      src/components/UserSearch/UserSearchLoading.tsx
  4. +19
    -0
      src/components/UserSearch/UserSearchWrapper.tsx
  5. +1
    -0
      src/components/UserSearch/index.ts

+ 47
- 0
src/app/(main)/user/page.tsx Voir le fichier

@@ -0,0 +1,47 @@
import { preloadTaskTemplates } from "@/app/api/tasks";
import TaskTemplateSearch from "@/components/TaskTemplateSearch";
import { getServerI18n } from "@/i18n";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { Metadata } from "next";
import Link from "next/link";
import { Suspense } from "react";

export const metadata: Metadata = {
title: "User",
};

const TaskTemplates: React.FC = async () => {
const { t } = await getServerI18n("user");
preloadTaskTemplates();

return (
<>
<Stack
direction="row"
justifyContent="space-between"
flexWrap="wrap"
rowGap={2}
>
<Typography variant="h4" marginInlineEnd={2}>
{t("User")}
</Typography>
<Button
variant="contained"
startIcon={<Add />}
LinkComponent={Link}
href="/tasks/create"
>
{t("Create Template")}
</Button>
</Stack>
{/* <Suspense fallback={<TaskTemplateSearch.Loading />}>
<TaskTemplateSearch />
</Suspense> */}
</>
);
};

export default TaskTemplates;

+ 95
- 0
src/components/UserSearch/UserSearch.tsx Voir le fichier

@@ -0,0 +1,95 @@
"use client";

import SearchBox, { Criterion } from "../SearchBox";
import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import SearchResults, { Column } from "../SearchResults/index";
import EditNote from "@mui/icons-material/EditNote";
import DeleteIcon from "@mui/icons-material/Delete";
import { useRouter } from "next/navigation";
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import { UserResult } from "@/app/api/user";
import { deleteUser } from "@/app/api/user/actions";

interface Props {
users: UserResult[];
}
type SearchQuery = Partial<Omit<UserResult, "id">>;
type SearchParamNames = keyof SearchQuery;

const UserSearch: React.FC<Props> = ({ users }) => {
const { t } = useTranslation();
const [filteredUser, setFilteredUser] = useState(users);
const router = useRouter();

const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
() => [
{
label: t("User Name"),
paramName: "title",
type: "text",
},
],
[t]
);

const onUserClick = useCallback(
(users: UserResult) => {
console.log(users);
router.push(`/settings/user/edit?id=${users.id}`)
},
[router, t]
);

const onDeleteClick = useCallback((users: UserResult) => {
deleteDialog(async () => {
await deleteUser(users.id);
successDialog(t("Delete Success"), t);
}, t);
}, []);

const columns = useMemo<Column<UserResult>[]>(
() => [
{
name: "action",
label: t("Edit"),
onClick: onUserClick,
buttonIcon: <EditNote />,
},
{ name: "name", label: t("UserName") },
{ name: "fullName", label: t("FullName") },
{ name: "title", label: t("Title") },
{ name: "department", label: t("Department") },
{ name: "email", label: t("Email") },
{ name: "phone1", label: t("Phone") },
{
name: "action",
label: t("Delete"),
onClick: onDeleteClick,
buttonIcon: <DeleteIcon />,
color: "error"
},
],
[t]
);

return (
<>
<SearchBox
criteria={searchCriteria}
onSearch={(query) => {
// setFilteredUser(
// users.filter(
// (t) =>
// t.name.toLowerCase().includes(query.name.toLowerCase()) &&
// t.code.toLowerCase().includes(query.code.toLowerCase()) &&
// t.description.toLowerCase().includes(query.description.toLowerCase())
// )
// )
}}
/>
<SearchResults<UserResult> items={filteredUser} columns={columns} />
</>
);
};
export default UserSearch;

+ 40
- 0
src/components/UserSearch/UserSearchLoading.tsx Voir le fichier

@@ -0,0 +1,40 @@
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Skeleton from "@mui/material/Skeleton";
import Stack from "@mui/material/Stack";
import React from "react";

// Can make this nicer
export const UserSearchLoading: React.FC = () => {
return (
<>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton
variant="rounded"
height={50}
width={100}
sx={{ alignSelf: "flex-end" }}
/>
</Stack>
</CardContent>
</Card>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
</Stack>
</CardContent>
</Card>
</>
);
};

export default UserSearchLoading;

+ 19
- 0
src/components/UserSearch/UserSearchWrapper.tsx Voir le fichier

@@ -0,0 +1,19 @@
import React from "react";
import UserSearch from "./UserSearch";
import UserSearchLoading from "./UserSearchLoading";
import { UserResult, fetchUser } from "@/app/api/user";

interface SubComponents {
Loading: typeof UserSearchLoading;
}

const UserSearchWrapper: React.FC & SubComponents = async () => {
const users = await fetchUser()
console.log(users);

return <UserSearch users={users} />;
};

UserSearchWrapper.Loading = UserSearchLoading;

export default UserSearchWrapper;

+ 1
- 0
src/components/UserSearch/index.ts Voir le fichier

@@ -0,0 +1 @@
export { default } from "./UserSearchWrapper";

Chargement…
Annuler
Enregistrer