Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions app/api/links/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export async function PUT(
const startDate = body?.startDate;
const endDate = body?.endDate;
const parentId = body?.parentId;
const customLabel = body?.customLabel; // Extract customLabel

const rawExplicitPlatform = typeof platform === "string" ? platform.trim() : null;
const explicitPlatform = rawExplicitPlatform && Object.keys(PLATFORM_ICONS).includes(rawExplicitPlatform)
Expand All @@ -60,7 +61,16 @@ export async function PUT(
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}

const data: { url?: string; isPublic?: boolean; label?: string; platform?: string; startDate?: Date | null; endDate?: Date | null; parentId?: string | null } = {};
const data: {
url?: string;
isPublic?: boolean;
label?: string;
platform?: string;
startDate?: Date | null;
endDate?: Date | null;
parentId?: string | null;
customLabel?: string | null; // Add customLabel to data object
} = {};

// Handle parentId changes (move link into/out of a group)
if (parentId !== undefined) {
Expand Down Expand Up @@ -98,6 +108,11 @@ export async function PUT(
data.label = activeLabel;
}

// Handle customLabel update
if (customLabel !== undefined) {
data.customLabel = customLabel?.trim() || null;
}

if (typeof url === "string") {
const validation = validateUrlBackend(url);
if (!validation.valid) {
Expand Down Expand Up @@ -317,7 +332,4 @@ export async function DELETE(
});

return NextResponse.json({ success: true });
}



}
23 changes: 21 additions & 2 deletions app/api/links/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export async function POST(req: Request) {

const body = await req.json();
const isGroup = body?.isGroup === true;
const customLabel = body?.label?.trim(); // Extract customLabel

const user = await prisma.user.findUnique({
where: { email: session.user.email },
Expand Down Expand Up @@ -87,6 +88,7 @@ export async function POST(req: Request) {
url: "",
isGroup: true,
position: (maxOrder._max.position ?? 0) + 1,
customLabel: groupLabel, // Save customLabel for groups too
},
});
}, {
Expand All @@ -112,7 +114,6 @@ export async function POST(req: Request) {

// --- Regular link creation ---
const rawUrl = body?.url?.trim();
const customLabel = body?.label?.trim();
const rawAlias = body?.alias?.trim();
const customAlias = rawAlias ? rawAlias.toLowerCase().replace(/[^a-z0-9-]/g, "") : undefined;
const parentId = body?.parentId || null;
Expand Down Expand Up @@ -243,6 +244,7 @@ export async function POST(req: Request) {
url: finalUrl,
position: (maxOrder._max.position ?? 0) + 1,
parentId: parentId,
customLabel: customLabel || null, // Save the custom label
},
});
}, {
Expand Down Expand Up @@ -302,6 +304,23 @@ export async function GET() {

const allLinks = await prisma.link.findMany({
where: { userId: user.id },
select: {
id: true,
platform: true,
alias: true,
label: true,
url: true,
position: true,
parentId: true,
isGroup: true,
isPublic: true,
createdAt: true,
updatedAt: true,
startDate: true,
endDate: true,
clicks: true,
customLabel: true, // Include customLabel in GET response
},
orderBy: [
{ position: 'asc' },
{ createdAt: 'asc' }
Expand All @@ -311,4 +330,4 @@ export async function GET() {
const links = nestLinks(allLinks);

return NextResponse.json({ links });
}
}
18 changes: 16 additions & 2 deletions app/dashboard/AddLinkBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default function AddLinkBox({
const [label, setLabel] = useState("");
const [alias, setAlias] = useState("");
const [platform, setPlatform] = useState("");
const [customLabel, setCustomLabel] = useState(""); // Added for custom label
const [loading, setLoading] = useState(false);
const [showAdvanced, setShowAdvanced] = useState(false);

Expand All @@ -45,6 +46,7 @@ export default function AddLinkBox({
setLabel("");
setAlias("");
setPlatform("");
setCustomLabel("");
onCancel?.();
}

Expand Down Expand Up @@ -82,6 +84,7 @@ export default function AddLinkBox({
label: finalLabel,
alias,
platform,
customLabel: customLabel.trim() || null, // Send customLabel
}),
});

Expand All @@ -98,6 +101,7 @@ export default function AddLinkBox({
setLabel("");
setAlias("");
setPlatform("");
setCustomLabel("");
setShowAdvanced(false);
} catch (err: unknown) {
const errorMessage = err instanceof Error ? err.message : "Failed to add link";
Expand Down Expand Up @@ -140,6 +144,16 @@ export default function AddLinkBox({
onChange={(e) => setUrl(e.target.value)}
/>

{/* Custom Label Input - Added */}
<Input
type="text"
placeholder="Custom label (optional) — overrides detected platform name"
value={customLabel}
onChange={(e) => setCustomLabel(e.target.value)}
maxLength={50}
className="w-full"
/>

<div>
<button
type="button"
Expand Down Expand Up @@ -167,9 +181,9 @@ export default function AddLinkBox({
Cancel
</Button>
<Button onClick={submit} disabled={loading} className="flex-1">
{loading ? "Adding…" : "Add link"}
{loading ? "Adding…" : "Add link"}
</Button>
</div>
</div>
);
}
}
21 changes: 17 additions & 4 deletions app/dashboard/LinkItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
} from "@/components/ui/select";
import { formatLabel, POPULAR_PLATFORMS } from "@/lib/platformHelpers";
import { PLATFORMS } from "@/lib/constants";

export function LinkItem({
dragListeners,
dragAttributes,
Expand All @@ -44,13 +45,14 @@ export function LinkItem({
dragAttributes?: DraggableAttributes;
link: ProfileLink;
username: string;
onUpdate: (id: string, url: string, label?: string, platform?: string, startDate?: Date | null, endDate?: Date | null) => Promise<boolean>;
onUpdate: (id: string, url: string, label?: string, platform?: string, startDate?: Date | null, endDate?: Date | null, customLabel?: string | null) => Promise<boolean>;
onToggleVisibility: (id: string, isPublic: boolean) => Promise<void>;
onDelete: (id: string) => Promise<void>;
}) {
const [editing, setEditing] = useState(false);
const [url, setUrl] = useState(link.url);
const [label, setLabel] = useState(link.label || "");
const [customLabel, setCustomLabel] = useState(link.customLabel || ""); // Added for custom label
const isStandardPlatform = Object.keys(PLATFORM_ICONS).includes(link.platform);
const initialPlatform = isStandardPlatform ? link.platform : PLATFORMS.WEBSITE;
const [platform, setPlatform] = useState(initialPlatform);
Expand Down Expand Up @@ -112,7 +114,7 @@ export function LinkItem({
return toast.error("Start date cannot be later than end date");
}

const success = await onUpdate(link.id, url, trimmedLabel, platform, startDate, endDate);
const success = await onUpdate(link.id, url, trimmedLabel, platform, startDate, endDate, customLabel.trim() || null);
if (success) {
setEditing(false);
}
Expand All @@ -128,7 +130,7 @@ export function LinkItem({

<div className="min-w-0">
<p className="font-medium capitalize">
{editing ? (label || platform) : (link.label || link.platform)}
{editing ? (label || platform) : (link.customLabel || link.label || link.platform)}
</p>
<p className="text-sm text-muted-foreground truncate">
{editing ? url : link.url}
Expand Down Expand Up @@ -195,6 +197,7 @@ export function LinkItem({
if (editing) {
setUrl(link.url);
setLabel(link.label || "");
setCustomLabel(link.customLabel || "");
setPlatform(initialPlatform);
setStartDate(link.startDate ? new Date(link.startDate) : null);
setEndDate(link.endDate ? new Date(link.endDate) : null);
Expand Down Expand Up @@ -255,6 +258,16 @@ export function LinkItem({
/>
</div>

{/* Custom Label Input - Added */}
<Input
type="text"
placeholder="Custom label (optional) — overrides detected platform name"
value={customLabel}
onChange={(e) => setCustomLabel(e.target.value)}
maxLength={50}
className="w-full"
/>

<details className="group border rounded-md p-3 [&_summary::-webkit-details-marker]:hidden">
<summary className="flex cursor-pointer items-center justify-between font-medium text-sm text-muted-foreground">
Advanced Settings
Expand Down Expand Up @@ -302,4 +315,4 @@ export function LinkItem({
)}
</div>
);
}
}
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ model Link {
alias String?
label String
url String
customLabel String?
position Int @default(0)
clicks Int @default(0)
isPublic Boolean @default(true)
Expand Down
Loading