Compare commits

...

2 Commits

Author SHA1 Message Date
hamid zarghami 9d8dd549dc get with slug
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-01 10:04:05 +03:30
hamid zarghami 42ce8fd892 sticker height 2026-06-01 09:57:53 +03:30
6 changed files with 120 additions and 121 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
VITE_API_URL=http://89.32.249.26:4010 VITE_API_URL=https://dpage-api.danakcorp.com
# VITE_API_URL=http://192.168.99.131:4000 # VITE_API_URL=http://192.168.99.131:4000
VITE_TOKEN_NAME=dpage-editor-t VITE_TOKEN_NAME=dpage-editor-t
VITE_REFRESH_TOKEN_NAME=dpage-editor-refresh-t VITE_REFRESH_TOKEN_NAME=dpage-editor-refresh-t
+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,6 +1,6 @@
import { useMemo } from "react";
import { useGetIconGroups } from "@/pages/editor/hooks/useIconData"; import { useGetIconGroups } from "@/pages/editor/hooks/useIconData";
import { STICKER_DRAG_MIME } from "@/pages/editor/types/IconTypes"; import { STICKER_DRAG_MIME } from "@/pages/editor/types/IconTypes";
import { useMemo } from "react";
const StickerInstruction = () => { const StickerInstruction = () => {
const { data, isLoading, isError } = useGetIconGroups(); const { data, isLoading, isError } = useGetIconGroups();
@@ -10,7 +10,10 @@ const StickerInstruction = () => {
return groups.flatMap((group) => group.icons); return groups.flatMap((group) => group.icons);
}, [data]); }, [data]);
const handleDragStart = (e: React.DragEvent<HTMLImageElement>, url: string) => { const handleDragStart = (
e: React.DragEvent<HTMLImageElement>,
url: string,
) => {
e.dataTransfer.setData(STICKER_DRAG_MIME, url); e.dataTransfer.setData(STICKER_DRAG_MIME, url);
e.dataTransfer.effectAllowed = "copy"; e.dataTransfer.effectAllowed = "copy";
}; };
@@ -35,7 +38,7 @@ const StickerInstruction = () => {
)} )}
{stickers.length > 0 && ( {stickers.length > 0 && (
<div className="grid grid-cols-3 gap-2 max-h-[320px] overflow-y-auto"> <div className="grid grid-cols-3 gap-2 overflow-y-auto">
{stickers.map((icon) => ( {stickers.map((icon) => (
<div <div
key={icon.id} key={icon.id}
+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;
}; };