(refactor) Move generateShareId to locationActions and apply to LocationCard

- Moved generateShareId from shareChecksum.ts to locationActions.ts as a server action
- Updated LocationCard to use shareID with checksum for proof of payment download link
- Replaced Link with AsyncLink to handle async shareID generation
- Commented out debug console.log in Pdf417Barcode

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-09 18:18:17 +01:00
parent e318523887
commit a3ec20544c
4 changed files with 36 additions and 20 deletions

View File

@@ -1,15 +1,16 @@
'use client';
import { CheckCircleIcon, Cog8ToothIcon, PlusCircleIcon, ShareIcon, BanknotesIcon, EyeIcon, TicketIcon, ShoppingCartIcon, EnvelopeIcon, ExclamationTriangleIcon, ClockIcon } from "@heroicons/react/24/outline";
import { FC } from "react";
import { FC, useEffect, useState } from "react";
import { BillBadge } from "./BillBadge";
import { BillingLocation, EmailStatus } from "../lib/db-types";
import { formatYearMonth } from "../lib/format";
import { formatCurrency } from "../lib/formatStrings";
import Link from "next/link";
import { useLocale, useTranslations } from "next-intl";
import { useTranslations } from "next-intl";
import { toast } from "react-toastify";
import { generateShareLink } from "../lib/actions/locationActions";
import { generateShareId, generateShareLink } from "../lib/actions/locationActions";
import { AsyncLink } from "./AsyncLink";
export interface LocationCardProps {
location: BillingLocation;
@@ -35,6 +36,18 @@ export const LocationCard: FC<LocationCardProps> = ({ location, currency }) => {
const totalUnpaid = bills.reduce((acc, bill) => !bill.paid ? acc + (bill.payedAmount ?? 0) : acc, 0);
const totalPayed = bills.reduce((acc, bill) => bill.paid ? acc + (bill.payedAmount ?? 0) : acc, 0);
/**
* Share ID which can be used in shareable links
* Note: not to be used in share button directly since `generateShareLink` sets sharing TTL in the DB
* */
const [shareID, setShareID] = useState<string>("not-yet-generated");
useEffect(() => {
// share ID can be generated server-side since it requires a secret key
// which we don't want to expose to the client
(async () => setShareID(await generateShareId(_id)))();
}, [_id]);
const handleCopyLinkClick = async () => {
// copy URL to clipboard
const shareLink = await generateShareLink(_id);
@@ -124,16 +137,17 @@ export const LocationCard: FC<LocationCardProps> = ({ location, currency }) => {
</div>
)}
{utilBillsProofOfPayment?.uploadedAt && (
<Link
href={`/share/proof-of-payment/${_id}/`}
<AsyncLink
href={`/share/proof-of-payment/combined/${shareID}`}
target="_blank"
className="flex mt-1 ml-1">
className="flex mt-1 ml-1"
disabled={!shareID} >
<span className="w-5 min-w-5 mr-2"><TicketIcon className="mt-[.1rem]" /></span>
<span>
<span className="underline">{t("download-proof-of-payment-label")}</span>
<CheckCircleIcon className="h-5 w-5 ml-2 mt-[-.2rem] text-success inline-block" />
</span>
</Link>
</AsyncLink>
)}
</div>
</div>