import { useEffect, useMemo, useState } from "react"; import { useHapticFeedback } from "@vkruglikov/react-telegram-web-app"; import { Input } from "~/shared/ui/input"; import { FormLabel } from "~/shared/ui/form-label"; import { XMark } from "~/shared/ui/icons/x-mark.tsx"; import { Button } from "~/shared/ui/button"; import { PercentHint } from "~/pages/root/steps/royalty-step/components/percent-hint"; import { cn } from "~/shared/utils"; import { Spread } from "~/shared/ui/icons/spread.tsx"; import { ConfirmModal } from "~/pages/root/steps/royalty-step/components/confirm-modal"; import { useRootStore } from "~/shared/stores/root"; import { BackButton } from "~/shared/ui/back-button"; import { useTonConnectUI } from "@tonconnect/ui-react"; import { Address } from "@ton/core"; import { FieldError } from "react-hook-form"; type RoyaltyStepProps = { prevStep(): void; nextStep(): void; }; const isValidTonAddress = (address: string): boolean => { try { if (!address) return false; Address.parse(address); return true; } catch { return false; } }; export const RoyaltyStep = ({ nextStep, prevStep }: RoyaltyStepProps) => { const [impactOccurred] = useHapticFeedback(); const [isDeleteAllOpen, setDeleteAllOpen] = useState(false); const [isSpreadOpen, setSpreadOpen] = useState(false); const [addressErrors, setAddressErrors] = useState>({}); const { royalty, setRoyalty, isPercentHintOpen, setPercentHintOpen } = useRootStore(); const handleAdd = () => { impactOccurred("light"); setRoyalty([...royalty, { address: "", value: 0 }]); }; const handleRemove = (index: number) => { if (royalty.length === 1) return; impactOccurred("light"); const newRoyalty = royalty.filter((_, i) => i !== index); setRoyalty(newRoyalty); }; const handleWalletChange = (index: number, address: string) => { const isValid = isValidTonAddress(address); setAddressErrors({ ...addressErrors, [index]: !isValid ? { type: 'validation', message: 'Неверный адрес TON' } : undefined }); const newRoyalty = royalty.map((member, i) => i === index ? { ...member, address } : member ); setRoyalty(newRoyalty); }; const handlePercentChange = (index: number, value: string) => { const percentNumber = parseInt(value, 10) || 0; const newRoyalty = royalty.map((royalty, i) => i === index ? { ...royalty, value: percentNumber } : royalty, ); setRoyalty(newRoyalty); }; const spreadPercentageEqually = () => { const equalPercent = 100 / royalty.length; const updatedRoyalty = royalty.map((member) => ({ ...member, value: equalPercent, })); setRoyalty(updatedRoyalty); }; const isValid = useMemo(() => { return ( royalty.every((member) => isValidTonAddress(member.address) && member.value >= 0) && royalty.reduce((acc, curr) => acc + curr.value, 0) === 100 ); }, [royalty]); const [tonConnectUI] = useTonConnectUI(); // Устанавливаем адрес из tonConnectUI.account при загрузке страницы useEffect(() => { if (!tonConnectUI.account) return; if (royalty.length === 0) { // First initialization with 100% setRoyalty([{ address: Address.parse(tonConnectUI.account.address).toString({ bounceable: true, urlSafe: true, testOnly: false, }), value: 100 }]); } }, [tonConnectUI.account, setRoyalty, royalty]); return (
{isPercentHintOpen && ( setPercentHintOpen(false)} /> )} {isDeleteAllOpen && ( { setRoyalty([{ address: "", value: 100 }]); setDeleteAllOpen(false); }} onCancel={() => { setDeleteAllOpen(false); }} /> )} {isSpreadOpen && ( { spreadPercentageEqually(); setSpreadOpen(false); }} onCancel={() => { setSpreadOpen(false); }} /> )}
/Заполните информацию об роялти
3/5
{royalty.map((member, index) => (
0 && ( ) } label={`Роялти_${index + 1}`} > handleWalletChange(index, e.target.value)} placeholder={"[ Введите адрес криптокошелька TON ]"} error={addressErrors[index]} />
handlePercentChange(index, e.target.value)} placeholder={"[ % ]"} className={cn({ "pointer-events-none z-50 border-primary": isPercentHintOpen, })} />
))}
{royalty.length > 1 && (
)}
); };