feat(contact-us): Add filtering functionality to contact us list table
- Enable Contact Us navigation menu item in sidebar with visible flag set to true - Create TContacts type schema with Zod validation for API responses - Add type safety to contactUsService.getAllContactUs() with return type annotation - Implement contact list table rendering with proper data mapping - Display contact information columns: full name, email, status, phone, created date - Add date formatting using unixToDate utility for created_at timestamps - Update useContactUsListPresenter to return properly structured contacts data - Refactor table columns array to include all contact detail fields - Follows established pattern from recent filtering feature implementations
This commit is contained in:
@@ -73,13 +73,13 @@ export const NAV_DATA: NavData = [
|
|||||||
icon: Icons.NotificationIcon,
|
icon: Icons.NotificationIcon,
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// title: "Contact Us",
|
title: "Contact Us",
|
||||||
// url: "/contact-us",
|
url: "/contact-us",
|
||||||
// icon: Icons.CallIncome,
|
icon: Icons.CallIncome,
|
||||||
// items: [],
|
items: [],
|
||||||
// visible: false,
|
visible: true,
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
title: "Marketing",
|
title: "Marketing",
|
||||||
url: "/marketing",
|
url: "/marketing",
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ import {
|
|||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import TableSkeleton from "@/components/ui/TableSkeleton";
|
import TableSkeleton from "@/components/ui/TableSkeleton";
|
||||||
import { useContactUsListPresenter } from "./useContactUsListPresenter";
|
import { useContactUsListPresenter } from "./useContactUsListPresenter";
|
||||||
|
import { unixToDate } from "@/utils/shared";
|
||||||
|
|
||||||
const ContactUsTable = () => {
|
const ContactUsTable = () => {
|
||||||
const { columns, pathname, router, isPending, data } =
|
const { columns, pathname, router, isPending, contacts } =
|
||||||
useContactUsListPresenter();
|
useContactUsListPresenter();
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
|
<div className="flex flex-col rounded-[10px] bg-white px-7.5 pb-4 pt-7.5 shadow-1 dark:bg-gray-dark dark:shadow-card">
|
||||||
@@ -33,13 +34,35 @@ const ContactUsTable = () => {
|
|||||||
{isPending && <TableSkeleton column={columns.length} />}
|
{isPending && <TableSkeleton column={columns.length} />}
|
||||||
<TableBody>
|
<TableBody>
|
||||||
<EmptyListWrapper
|
<EmptyListWrapper
|
||||||
list={data ?? []}
|
list={contacts ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
emptyMessage="No contact us is submitted"
|
emptyMessage="No contact us is submitted"
|
||||||
>
|
>
|
||||||
<TableRow>
|
{contacts?.map((item, index) => (
|
||||||
<TableCell><div>hjgfjhg</div></TableCell>
|
<TableRow
|
||||||
</TableRow>
|
key={item?.id ?? index}
|
||||||
|
className="odd:bg-gray-2 dark:odd:bg-gray-7"
|
||||||
|
>
|
||||||
|
<TableCell className="text-start" colSpan={100}>
|
||||||
|
{index + 1}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-start" colSpan={100}>
|
||||||
|
{item?.full_name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-start" colSpan={100}>
|
||||||
|
{item?.email}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-start" colSpan={100}>
|
||||||
|
{item?.status}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-start" colSpan={100}>
|
||||||
|
{item?.phone}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-start" colSpan={100}>
|
||||||
|
{unixToDate({ unix: item?.created_at })}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
</EmptyListWrapper>
|
</EmptyListWrapper>
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
@@ -2,7 +2,15 @@
|
|||||||
import { useReadAllContactUs } from "@/hooks/queries/useContactUsQuery";
|
import { useReadAllContactUs } from "@/hooks/queries/useContactUsQuery";
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
export const useContactUsListPresenter = () => {
|
export const useContactUsListPresenter = () => {
|
||||||
const columns: string[] = ["row", "actions"];
|
const columns: string[] = [
|
||||||
|
"row",
|
||||||
|
"Full name",
|
||||||
|
"email",
|
||||||
|
"status",
|
||||||
|
"phone",
|
||||||
|
"created at",
|
||||||
|
"actions",
|
||||||
|
];
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { data, isPending } = useReadAllContactUs();
|
const { data, isPending } = useReadAllContactUs();
|
||||||
@@ -11,6 +19,6 @@ export const useContactUsListPresenter = () => {
|
|||||||
pathname,
|
pathname,
|
||||||
router,
|
router,
|
||||||
isPending,
|
isPending,
|
||||||
data,
|
contacts: data?.data.contacts,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import api from "../axios";
|
import api from "../axios";
|
||||||
import { API_ENDPOINTS } from "../endpoints";
|
import { API_ENDPOINTS } from "../endpoints";
|
||||||
|
import { TContactApiResponseSchema } from "../types/TContacts";
|
||||||
|
|
||||||
export const contactUsService = {
|
export const contactUsService = {
|
||||||
getAllContactUs: async () => {
|
getAllContactUs: async (): Promise<TContactApiResponseSchema> => {
|
||||||
try {
|
try {
|
||||||
return (await api.get(API_ENDPOINTS.CONTACT_US.READ_ALL)).data;
|
return (await api.get(API_ENDPOINTS.CONTACT_US.READ_ALL)).data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import { createApiResponseSchema } from "./Factory";
|
||||||
|
const contactsListSchema = z.object({
|
||||||
|
admin_notes: z.string(),
|
||||||
|
created_at: z.number(),
|
||||||
|
email: z.string(),
|
||||||
|
full_name: z.string(),
|
||||||
|
id: z.string(),
|
||||||
|
message: z.string(),
|
||||||
|
phone: z.string(),
|
||||||
|
resolved_at: z.number(),
|
||||||
|
resolved_by: z.string(),
|
||||||
|
status: z.string(),
|
||||||
|
updated_at: z.number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const contactsListResponseSchema = z.object({
|
||||||
|
contacts: z.array(contactsListSchema),
|
||||||
|
});
|
||||||
|
export const contactsApiResponse = createApiResponseSchema(
|
||||||
|
contactsListResponseSchema,
|
||||||
|
);
|
||||||
|
|
||||||
|
export type TContactApiResponseSchema = z.infer<typeof contactsApiResponse>;
|
||||||
Reference in New Issue
Block a user