get with slug
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
hamid zarghami
2026-06-01 10:04:05 +03:30
parent 42ce8fd892
commit 9d8dd549dc
4 changed files with 113 additions and 117 deletions
+19 -24
View File
@@ -1,16 +1,15 @@
import { type FC } from 'react' import GridWrapper from "@/components/GridWrapper";
import { useGetCatalog } from '../home/hooks/useHomeData' import { type FC } from "react";
import GridWrapper from '@/components/GridWrapper' import { useGetCatalog } from "../home/hooks/useHomeData";
import CatalogueItem from './components/CatalogueItem' import ButtonAddCatalogue from "./components/ButtonAddCatalogue";
import ButtonAddCatalogue from './components/ButtonAddCatalogue' import CatalogueItem from "./components/CatalogueItem";
const CatalogueList: FC = () => { const CatalogueList: FC = () => {
const { data, refetch } = useGetCatalog();
const { data, refetch } = useGetCatalog() return (
<div className="w-full mt-5">
return ( {/* {
<div className='w-full mt-5'>
{/* {
!isPending && !data?.data?.length && !isPending && !data?.data?.length &&
<div className='flex flex-col items-center gap-5'> <div className='flex flex-col items-center gap-5'>
<div className='text-gray-500'> <div className='text-gray-500'>
@@ -24,18 +23,14 @@ const CatalogueList: FC = () => {
</Link> </Link>
</div> </div>
} */} } */}
<GridWrapper desktop={4} gapDesktop={40} mobile={1}> <GridWrapper desktop={4} gapDesktop={40} mobile={1}>
{ {data?.data?.map((item) => {
data?.data?.map((item) => { return <CatalogueItem refetch={refetch} key={item.id} item={item} />;
return ( })}
<CatalogueItem refetch={refetch} key={item.id} item={item} /> <ButtonAddCatalogue isFirst={data?.data?.length === 0} />
) </GridWrapper>
}) </div>
} );
<ButtonAddCatalogue isFirst={data?.data?.length === 0} /> };
</GridWrapper>
</div>
)
}
export default CatalogueList export default CatalogueList;
@@ -1,103 +1,103 @@
import { type FC } from 'react' import { toast } from "@/components/Toast";
import { Edit, Eye, Share } from 'iconsax-react' import TrashWithConfrim from "@/components/TrashWithConfrim";
import type { CatalogItemType } from '../types/Types' import { Paths } from "@/config/Paths";
import moment from 'moment-jalaali' import { extractErrorMessage } from "@/helpers/utils";
import { Link } from 'react-router-dom' import { useDleteCatalog } from "@/pages/home/hooks/useHomeData";
import { Paths } from '@/config/Paths' import { requestViewerFullscreen } from "@/pages/viewer/utils/viewerFullscreen";
import CatalogPreview from './CatalogPreview' import { Edit, Eye, Share } from "iconsax-react";
import TrashWithConfrim from '@/components/TrashWithConfrim' import moment from "moment-jalaali";
import { useDleteCatalog } from '@/pages/home/hooks/useHomeData' import { type FC } from "react";
import { toast } from '@/components/Toast' import { Link } from "react-router-dom";
import { extractErrorMessage } from '@/helpers/utils' import type { CatalogItemType } from "../types/Types";
import { requestViewerFullscreen } from '@/pages/viewer/utils/viewerFullscreen' import CatalogPreview from "./CatalogPreview";
type Props = { type Props = {
item: CatalogItemType, item: CatalogItemType;
refetch: () => void, refetch: () => void;
} };
const CatalogueItem: FC<Props> = ({ item, refetch }) => { const CatalogueItem: FC<Props> = ({ item, refetch }) => {
const deleteCatalog = useDleteCatalog();
const deleteCatalog = useDleteCatalog() const shareUrl = `${window.location.origin}${Paths.viewer}/${item.id}`;
const shareUrl = `${window.location.origin}${Paths.viewer}/${item.id}` const handleShare = async () => {
try {
const handleShare = async () => { if (typeof navigator.share === "function") {
try { await navigator.share({
if (typeof navigator.share === 'function') { title: item.name,
await navigator.share({ text: item.name,
title: item.name, url: shareUrl,
text: item.name, });
url: shareUrl, return;
}) }
return await navigator.clipboard.writeText(shareUrl);
} toast("لینک در کلیپ‌بورد کپی شد", "success");
await navigator.clipboard.writeText(shareUrl) } catch (err) {
toast('لینک در کلیپ‌بورد کپی شد', 'success') const isAbort =
} catch (err) { err instanceof DOMException
const isAbort = ? err.name === "AbortError"
err instanceof DOMException : err instanceof Error && err.name === "AbortError";
? err.name === 'AbortError' if (isAbort) return;
: err instanceof Error && err.name === 'AbortError' toast(extractErrorMessage(err, "امکان اشتراک‌گذاری وجود ندارد"), "error");
if (isAbort) return
toast(extractErrorMessage(err, 'امکان اشتراک‌گذاری وجود ندارد'), 'error')
}
} }
};
const handleDelete = () => { const handleDelete = () => {
deleteCatalog.mutate(item.id, { deleteCatalog.mutate(item.id, {
onSuccess: () => { onSuccess: () => {
toast('با موفقیت حذف شد', 'success') toast("با موفقیت حذف شد", "success");
refetch() refetch();
}, },
onError: (error) => { onError: (error) => {
toast(extractErrorMessage(error, 'error')) toast(extractErrorMessage(error, "error"));
} },
}) });
} };
return ( return (
<div className='bg-white p-6 rounded-3xl w-full'> <div className="bg-white p-6 rounded-3xl w-full">
<div className='flex gap-4 items-center'> <div className="flex gap-4 items-center">
<CatalogPreview item={item} /> <CatalogPreview item={item} />
<div> <div>
<h6> <h6>{item.name}</h6>
{item.name} <div className="mt-2 text-[#999999] text-xs">
</h6> {moment(item.createdAt).format("jYYYY/jMM/jDD")}
<div className='mt-2 text-[#999999] text-xs'> </div>
{moment(item.createdAt).format('jYYYY/jMM/jDD')}
</div>
</div>
</div>
<div className='flex justify-end gap-1 items-center mt-1'>
<Link to={Paths.viewer + `/${item.id}`} onClick={requestViewerFullscreen}>
<div className='size-6 bg-[#EAECF4] rounded-md flex justify-center items-center'>
<Eye size={18} color='#0047FF' />
</div>
</Link>
<Link to={Paths.editor + `/${item.id}`}>
<div className='size-6 bg-[#EAECF4] rounded-md flex justify-center items-center'>
<Edit size={18} color='#0047FF' />
</div>
</Link>
<button
type='button'
onClick={handleShare}
className='size-6 bg-[#EAECF4] rounded-md flex justify-center items-center border-0 p-0 cursor-pointer shrink-0'
aria-label='اشتراک‌گذاری'
>
<Share size={18} color='#000' />
</button>
<div className='size-6 bg-[#EAECF4] rounded-md flex justify-center items-center'>
<TrashWithConfrim
onDelete={handleDelete}
colorIcon='red'
isloading={deleteCatalog.isPending}
/>
</div>
</div>
</div> </div>
) </div>
} <div className="flex justify-end gap-1 items-center mt-1">
<Link
to={Paths.viewer + `/${item.slug}`}
onClick={requestViewerFullscreen}
>
<div className="size-6 bg-[#EAECF4] rounded-md flex justify-center items-center">
<Eye size={18} color="#0047FF" />
</div>
</Link>
<Link to={Paths.editor + `/${item.slug}`}>
<div className="size-6 bg-[#EAECF4] rounded-md flex justify-center items-center">
<Edit size={18} color="#0047FF" />
</div>
</Link>
<button
type="button"
onClick={handleShare}
className="size-6 bg-[#EAECF4] rounded-md flex justify-center items-center border-0 p-0 cursor-pointer shrink-0"
aria-label="اشتراک‌گذاری"
>
<Share size={18} color="#000" />
</button>
<div className="size-6 bg-[#EAECF4] rounded-md flex justify-center items-center">
<TrashWithConfrim
onDelete={handleDelete}
colorIcon="red"
isloading={deleteCatalog.isPending}
/>
</div>
</div>
</div>
);
};
export default CatalogueItem export default CatalogueItem;
+1
View File
@@ -7,6 +7,7 @@ export type CatalogItemType = {
size: string; size: string;
status: string; status: string;
createdAt: string; createdAt: string;
slug: string;
}; };
export type CatalogResponseType = BaseResponse<CatalogItemType[]>; export type CatalogResponseType = BaseResponse<CatalogItemType[]>;
+1 -1
View File
@@ -20,7 +20,7 @@ export const getCatalogs = async () => {
export const getCatalogById = async (id: string) => { export const getCatalogById = async (id: string) => {
const { data } = await axios.get<CatalogByIdResponseType>( const { data } = await axios.get<CatalogByIdResponseType>(
`/public/catalogue/${id}`, `/public/catalogue/slug/${id}`,
); );
return data; return data;
}; };