(refactor) dbTypes: added utilBillsProofOfPaymentUploadedAt to BillingLocation

This commit is contained in:
Knee Cola
2025-11-23 22:13:09 +01:00
parent 7a01dad5e7
commit fcecaaa901
4 changed files with 28 additions and 17 deletions

View File

@@ -435,6 +435,7 @@ export const fetchAllLocations = withUser(async (user:AuthenticatedUser, year:nu
// "bills.hub3aText": 1, // "bills.hub3aText": 1,
// project only file name - leave out file content so that // project only file name - leave out file content so that
// less data is transferred to the client // less data is transferred to the client
"utilBillsProofOfPaymentUploadedAt": 1,
"utilBillsProofOfPaymentAttachment.fileName": 1, "utilBillsProofOfPaymentAttachment.fileName": 1,
}, },
}, },

View File

@@ -41,6 +41,7 @@ export const addMonth = withUser(async (user:AuthenticatedUser, { year, month }:
...prevLocation, ...prevLocation,
// clear properties specific to the month // clear properties specific to the month
seenByTenant: undefined, seenByTenant: undefined,
utilBillsProofOfPaymentUploadedAt: undefined,
utilBillsProofOfPaymentAttachment: undefined, utilBillsProofOfPaymentAttachment: undefined,
// assign a new ID // assign a new ID
_id: (new ObjectId()).toHexString(), _id: (new ObjectId()).toHexString(),

View File

@@ -23,7 +23,7 @@ export const LocationCard: FC<LocationCardProps> = ({ location, currency }) => {
bills, bills,
seenByTenant, seenByTenant,
// NOTE: only the fileName is projected from the DB to reduce data transfer // NOTE: only the fileName is projected from the DB to reduce data transfer
utilBillsProofOfPaymentAttachment utilBillsProofOfPaymentUploadedAt
} = location; } = location;
const t = useTranslations("home-page.location-card"); const t = useTranslations("home-page.location-card");
@@ -58,7 +58,7 @@ export const LocationCard: FC<LocationCardProps> = ({ location, currency }) => {
</div> </div>
{monthlyExpense > 0 || seenByTenant || utilBillsProofOfPaymentAttachment ? {monthlyExpense > 0 || seenByTenant || utilBillsProofOfPaymentUploadedAt ?
<fieldset className="card card-compact card-bordered border-1 border-neutral p-3 mt-2 mr-[3.5rem]"> <fieldset className="card card-compact card-bordered border-1 border-neutral p-3 mt-2 mr-[3.5rem]">
<legend className="fieldset-legend px-2 text-sm font-semibold uppercase">{t("monthly-statement-legend")}</legend> <legend className="fieldset-legend px-2 text-sm font-semibold uppercase">{t("monthly-statement-legend")}</legend>
@@ -78,7 +78,7 @@ export const LocationCard: FC<LocationCardProps> = ({ location, currency }) => {
<CheckCircleIcon className="h-5 w-5 text-success" /> <CheckCircleIcon className="h-5 w-5 text-success" />
</div> </div>
)} )}
{utilBillsProofOfPaymentAttachment && ( {utilBillsProofOfPaymentUploadedAt && (
<Link <Link
href={`/share/proof-of-payment/${_id}/`} href={`/share/proof-of-payment/${_id}/`}
target="_blank" target="_blank"

View File

@@ -29,13 +29,15 @@ export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettin
tenantTown, tenantTown,
generateTenantCode, generateTenantCode,
// NOTE: only the fileName is projected from the DB to reduce data transfer // NOTE: only the fileName is projected from the DB to reduce data transfer
utilBillsProofOfPaymentAttachment utilBillsProofOfPaymentAttachment,
utilBillsProofOfPaymentUploadedAt,
} = location; } = location;
const t = useTranslations("home-page.location-card"); const t = useTranslations("home-page.location-card");
const [isUploading, setIsUploading] = useState(false); const [isUploading, setIsUploading] = useState(false);
const [uploadError, setUploadError] = useState<string | null>(null); const [uploadError, setUploadError] = useState<string | null>(null);
const [attachmentUploadedAt, setAttachmentUploadedAt ] = useState<Date | null>(utilBillsProofOfPaymentUploadedAt ?? null);
const [attachmentFilename, setAttachmentFilename] = useState(utilBillsProofOfPaymentAttachment?.fileName); const [attachmentFilename, setAttachmentFilename] = useState(utilBillsProofOfPaymentAttachment?.fileName);
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => { const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -60,6 +62,7 @@ export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettin
if (result.success) { if (result.success) {
setAttachmentFilename(file.name); setAttachmentFilename(file.name);
setAttachmentUploadedAt(new Date());
} else { } else {
setUploadError(result.error || 'Upload failed'); setUploadError(result.error || 'Upload failed');
} }
@@ -144,19 +147,25 @@ export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettin
} }
<fieldset className="fieldset bg-base-200 border-base-300 rounded-box w-xs border p-4 pb-2 pt-0 mt-2"> <fieldset className="fieldset bg-base-200 border-base-300 rounded-box w-xs border p-4 pb-2 pt-0 mt-2">
<legend className="fieldset-legend font-semibold uppercase">{t("upload-proof-of-payment-legend")}</legend> <legend className="fieldset-legend font-semibold uppercase">{t("upload-proof-of-payment-legend")}</legend>
{
{attachmentFilename ? ( // IF proof of payment was uploaded
<div className="mt-3 ml-[-.5rem]"> attachmentUploadedAt ? (
<Link // IF file name is available, show link to download
href={`/share/proof-of-payment/${_id}/`} // ELSE it's not available that means that the uploaded file was purged by housekeeping
target="_blank" // -> don't show anything
className='text-center w-full max-w-[20rem] text-nowrap truncate inline-block' attachmentFilename ? (
> <div className="mt-3 ml-[-.5rem]">
<DocumentIcon className="h-[1em] w-[1em] text-2xl inline-block mr-1" /> <Link
{decodeURIComponent(attachmentFilename)} href={`/share/proof-of-payment/${_id}/`}
</Link> target="_blank"
</div> className='text-center w-full max-w-[20rem] text-nowrap truncate inline-block'
) : ( >
<DocumentIcon className="h-[1em] w-[1em] text-2xl inline-block mr-1" />
{decodeURIComponent(attachmentFilename)}
</Link>
</div>
) : null
) : /* ELSE show upload input */ (
<div className="form-control w-full"> <div className="form-control w-full">
<label className="label"> <label className="label">
<span className="label-text">{t("upload-proof-of-payment-label")}</span> <span className="label-text">{t("upload-proof-of-payment-label")}</span>