From 5f4b83b09caec4105ba4713b1688c02a09f9d5ee Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 15 Aug 2025 11:11:24 -0700 Subject: [PATCH] Link editing. --- src/app/(main)/links/LinkDeleteButton.tsx | 3 +- src/app/(main)/links/LinkEditButton.tsx | 2 +- src/app/(main)/links/LinkEditForm.tsx | 77 ++++++++++++++------ src/app/(main)/links/LinksTable.tsx | 3 +- src/app/(main)/pixels/PixelsTable.tsx | 7 +- src/app/api/links/[linkId]/route.ts | 47 +++++------- src/app/api/pixels/[pixelId]/route.ts | 51 ++++++------- src/app/api/pixels/route.ts | 4 +- src/app/api/websites/[websiteId]/route.ts | 4 +- src/components/hooks/queries/useLinkQuery.ts | 2 +- src/components/messages.ts | 1 + src/lib/constants.ts | 2 + src/lib/url.ts | 9 +++ 13 files changed, 123 insertions(+), 89 deletions(-) diff --git a/src/app/(main)/links/LinkDeleteButton.tsx b/src/app/(main)/links/LinkDeleteButton.tsx index 58d9c1f6..276f4e8f 100644 --- a/src/app/(main)/links/LinkDeleteButton.tsx +++ b/src/app/(main)/links/LinkDeleteButton.tsx @@ -7,7 +7,6 @@ import { useApi, useMessages, useModified } from '@/components/hooks'; export function LinkDeleteButton({ linkId, - websiteId, name, onSave, }: { @@ -19,7 +18,7 @@ export function LinkDeleteButton({ const { formatMessage, labels } = useMessages(); const { del, useMutation } = useApi(); const { mutate, isPending, error } = useMutation({ - mutationFn: () => del(`/websites/${websiteId}/links/${linkId}`), + mutationFn: () => del(`/links/${linkId}`), }); const { touch } = useModified(); diff --git a/src/app/(main)/links/LinkEditButton.tsx b/src/app/(main)/links/LinkEditButton.tsx index e676e6ae..06f7a5c5 100644 --- a/src/app/(main)/links/LinkEditButton.tsx +++ b/src/app/(main)/links/LinkEditButton.tsx @@ -9,7 +9,7 @@ export function LinkEditButton({ linkId }: { linkId: string }) { return ( }> - + {({ close }) => { return ; }} diff --git a/src/app/(main)/links/LinkEditForm.tsx b/src/app/(main)/links/LinkEditForm.tsx index f46081ee..a6257768 100644 --- a/src/app/(main)/links/LinkEditForm.tsx +++ b/src/app/(main)/links/LinkEditForm.tsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from 'react'; import { Form, FormField, @@ -5,7 +6,6 @@ import { Row, TextField, Button, - Text, Label, Column, Icon, @@ -16,6 +16,8 @@ import { useMessages } from '@/components/hooks'; import { Refresh } from '@/components/icons'; import { getRandomChars } from '@/lib/crypto'; import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery'; +import { LINKS_URL } from '@/lib/constants'; +import { isValidUrl } from '@/lib/url'; const generateId = () => getRandomChars(9); @@ -31,29 +33,55 @@ export function LinkEditForm({ onClose?: () => void; }) { const { formatMessage, labels } = useMessages(); - const { mutate, error, isPending } = useUpdateQuery('/links', { id: linkId, teamId }); - const { linkDomain } = useConfig(); + const { mutate, error, isPending, touch } = useUpdateQuery( + linkId ? `/links/${linkId}` : '/links', + { + id: linkId, + teamId, + }, + ); + const { linksUrl } = useConfig(); + const hostUrl = linksUrl || LINKS_URL; const { data, isLoading } = useLinkQuery(linkId); + const [slug, setSlug] = useState(generateId()); const handleSubmit = async (data: any) => { mutate(data, { onSuccess: async () => { + touch('links'); onSave?.(); onClose?.(); }, }); }; - if (linkId && !isLoading) { + const handleSlug = () => { + const slug = generateId(); + + setSlug(slug); + + return slug; + }; + + const checkUrl = (url: string) => { + if (!isValidUrl(url)) { + return formatMessage(labels.invalidUrl); + } + return true; + }; + + useEffect(() => { + if (data) { + setSlug(data.slug); + } + }, [data]); + + if (linkId && isLoading) { return ; } return ( -
+ {({ setValue }) => { return ( <> @@ -62,33 +90,40 @@ export function LinkEditForm({ name="name" rules={{ required: formatMessage(labels.required) }} > - + + + + + - {linkDomain || window.location.origin}/ - - - + />