Files
dpage-editor/src/pages/editor/components/sidebar/instructions/LinkInput.tsx
T
hamid zarghami 914389c082 update in link
2026-05-10 11:49:35 +03:30

178 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState, useMemo, type ComponentType } from "react";
import { useEditorStore, type ToolType } from "@/pages/editor/store/editorStore";
import Input from "@/components/Input";
import Button from "@/components/Button";
import Select from "@/components/Select";
import {
Link,
ArrowCircleRight,
ArrowCircleLeft,
DocumentText,
ArrowLeft,
ArrowRight,
Add,
} from "iconsax-react";
import { clx } from "@/helpers/utils";
type LinkType = "link" | "nextPage" | "prevPage" | "page" | "firstPage" | "lastPrev";
const linkTypesConfig: Record<
LinkType,
{ icon: ComponentType<{ size?: number; color?: string }>; label: string }
> = {
link: { icon: Link, label: "لینک" },
nextPage: { icon: ArrowCircleRight, label: "صفحه بعدی" },
prevPage: { icon: ArrowCircleLeft, label: "صفحه قبلی" },
page: { icon: DocumentText, label: "صفحه" },
firstPage: { icon: ArrowLeft, label: "اولین صفحه" },
lastPrev: { icon: ArrowRight, label: "آخرین صفحه" },
};
const internalLinkUrls: Partial<Record<LinkType, string>> = {
nextPage: "page://next",
prevPage: "page://prev",
firstPage: "page://first",
lastPrev: "page://last",
};
const LinkInput = () => {
const [selectedLinkType, setSelectedLinkType] = useState<LinkType>("link");
const [linkUrl, setLinkUrl] = useState("");
const [linkTitle, setLinkTitle] = useState("");
const [targetPageNumber, setTargetPageNumber] = useState("");
const pages = useEditorStore((state) => state.pages);
const linkTypes = useMemo(
() =>
(Object.entries(linkTypesConfig) as [LinkType, typeof linkTypesConfig[LinkType]][])
.map(([type, config]) => ({
type,
...config,
})),
[]
);
const pageOptions = useMemo(
() =>
pages.map((page, index) => ({
value: String(index + 1),
label: page.name || `صفحه ${index + 1}`,
})),
[pages]
);
const selectedLinkConfig = linkTypesConfig[selectedLinkType];
const selectedPage = targetPageNumber
? pageOptions.find((page) => page.value === targetPageNumber)
: undefined;
const resolvedLinkUrl =
selectedLinkType === "link"
? linkUrl.trim()
: internalLinkUrls[selectedLinkType] ?? (targetPageNumber ? `page://${targetPageNumber}` : "");
const defaultLinkText =
selectedLinkType === "link"
? resolvedLinkUrl
: selectedLinkType === "page"
? selectedPage?.label || selectedLinkConfig.label
: selectedLinkConfig.label;
const isAddDisabled =
selectedLinkType === "link"
? !linkUrl.trim()
: selectedLinkType === "page" && !targetPageNumber;
const handleAddLink = () => {
if (!resolvedLinkUrl) return;
const newLink = {
id: `link-${Date.now()}`,
type: "link" as ToolType,
x: 100,
y: 100,
text: linkTitle.trim() || defaultLinkText,
linkUrl: resolvedLinkUrl,
fontSize: 24,
fill: "#0000ff",
fontWeight: "normal",
};
const { addObject, setSelectedObjectId, setTool } = useEditorStore.getState();
addObject(newLink);
setSelectedObjectId(newLink.id);
setTool("select");
setLinkUrl("");
setLinkTitle("");
setTargetPageNumber("");
};
return (
<div className="space-y-6">
<h2 className="text-lg font-semibold text-right">لینک ها</h2>
<div className="grid grid-cols-2 gap-3">
{linkTypes.map((item) => {
const isSelected = selectedLinkType === item.type;
const Icon = item.icon;
return (
<button
key={item.type}
onClick={() => setSelectedLinkType(item.type)}
className={clx(
"flex flex-col items-center justify-center gap-2 p-4 rounded-xl bg-gray-50 border transition-colors shadow-sm",
isSelected
? "border-black border-2"
: "border-gray-200 hover:border-gray-300"
)}
>
<Icon size={20} color="black" />
<span className="text-xs text-black">{item.label}</span>
</button>
);
})}
</div>
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-sm font-medium text-right">عنوان لینک</h3>
<Input
value={linkTitle}
onChange={(e) => setLinkTitle(e.target.value)}
placeholder="عنوان لینک"
/>
</div>
{selectedLinkType === "link" ? (
<div className="space-y-2">
<h3 className="text-sm font-medium text-right">لینک</h3>
<Input
value={linkUrl}
onChange={(e) => setLinkUrl(e.target.value)}
placeholder="https://example.com"
onEnter={handleAddLink}
/>
</div>
) : null}
{selectedLinkType === "page" ? (
<div className="space-y-2">
<h3 className="text-sm font-medium text-right">انتخاب صفحه</h3>
<Select
value={targetPageNumber}
onChange={(e) => setTargetPageNumber(e.target.value)}
placeholder="صفحه مقصد را انتخاب کنید"
items={pageOptions}
/>
</div>
) : null}
<Button
onClick={handleAddLink}
disabled={isAddDisabled}
className="w-full"
leftIcon={<Add size={20} color="white" />}
>
افزودن
</Button>
</div>
</div>
);
};
export default LinkInput;