feat: add persistence for tenant email status field
- Add tenantEmailStatus hidden field to LocationEditForm - Update locationActions to persist email status across all scopes - Add reset button for unsubscribed email status - Improve email status display with new/modified indicators - Update translations for email status messages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { TrashIcon, ExclamationTriangleIcon, ClockIcon, EnvelopeIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
|
||||
import { TrashIcon, ExclamationTriangleIcon, ClockIcon, EnvelopeIcon, CheckCircleIcon, PencilSquareIcon } from "@heroicons/react/24/outline";
|
||||
import { FC, useState } from "react";
|
||||
import { BillingLocation, UserSettings, YearMonth, EmailStatus } from "../lib/db-types";
|
||||
import { updateOrAddLocation } from "../lib/actions/locationActions";
|
||||
@@ -41,6 +41,7 @@ export const LocationEditForm: FC<LocationEditFormProps> = ({ location, yearMont
|
||||
tenantStreet: location?.tenantStreet ?? "",
|
||||
tenantTown: location?.tenantTown ?? "",
|
||||
tenantEmail: location?.tenantEmail ?? "",
|
||||
tenantEmailStatus: location?.tenantEmailStatus ?? EmailStatus.Unverified,
|
||||
tenantPaymentMethod: location?.tenantPaymentMethod ?? "none",
|
||||
proofOfPaymentType: location?.proofOfPaymentType ?? "none",
|
||||
autoBillFwd: location?.autoBillFwd ?? false,
|
||||
@@ -50,10 +51,21 @@ export const LocationEditForm: FC<LocationEditFormProps> = ({ location, yearMont
|
||||
rentDueDay: location?.rentDueDay ?? 1,
|
||||
});
|
||||
|
||||
// tenant e-mail fetched from database
|
||||
const [dbTenantEmail, setDbTenantEmail] = useState(location?.tenantEmail ?? "");
|
||||
|
||||
const handleInputChange = (field: keyof typeof formValues, value: string | boolean | number) => {
|
||||
setFormValues(prev => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
const handleResetEmailStatus = () => {
|
||||
// this will simulate that the email
|
||||
// is new and needs verification
|
||||
setDbTenantEmail("");
|
||||
// reset the email status to unverified
|
||||
setFormValues(prev => ({ ...prev, tenantEmailStatus: EmailStatus.Unverified }));
|
||||
};
|
||||
|
||||
let { year, month } = location ? location.yearMonth : yearMonth;
|
||||
|
||||
return (
|
||||
@@ -355,37 +367,45 @@ export const LocationEditForm: FC<LocationEditFormProps> = ({ location, yearMont
|
||||
defaultValue={formValues.tenantEmail}
|
||||
onChange={(e) => handleInputChange("tenantEmail", e.target.value)}
|
||||
/>
|
||||
{location?.tenantEmail && location?.tenantEmail === formValues.tenantEmail && location?.tenantEmailStatus ? (
|
||||
<input
|
||||
id="tenantEmailStatus"
|
||||
name="tenantEmailStatus"
|
||||
type="hidden"
|
||||
maxLength={30}
|
||||
defaultValue={formValues.tenantEmailStatus}
|
||||
/>
|
||||
{dbTenantEmail === formValues.tenantEmail ? (
|
||||
<div className="flex items-center gap-2 mt-2 ml-2">
|
||||
{location.tenantEmailStatus === EmailStatus.Unverified && (
|
||||
{location?.tenantEmailStatus === EmailStatus.Unverified && (
|
||||
<>
|
||||
<ExclamationTriangleIcon className="h-5 w-5 text-warning" />
|
||||
<span className="text-sm text-warning">{t("email-status.unverified")}</span>
|
||||
</>
|
||||
)}
|
||||
{location.tenantEmailStatus === EmailStatus.VerificationPending && (
|
||||
{location?.tenantEmailStatus === EmailStatus.VerificationPending && (
|
||||
<>
|
||||
<ClockIcon className="h-5 w-5 text-info" />
|
||||
<span className="text-sm text-info">{t("email-status.verification-pending")}</span>
|
||||
</>
|
||||
)}
|
||||
{location.tenantEmailStatus === EmailStatus.Verified && (
|
||||
{location?.tenantEmailStatus === EmailStatus.Verified && (
|
||||
<>
|
||||
<CheckCircleIcon className="h-5 w-5 text-success" />
|
||||
<span className="text-sm text-success">{t("email-status.verified")}</span>
|
||||
</>
|
||||
)}
|
||||
{location.tenantEmailStatus === EmailStatus.Unsubscribed && (
|
||||
{location?.tenantEmailStatus === EmailStatus.Unsubscribed && (
|
||||
<>
|
||||
<EnvelopeIcon className="h-5 w-5 text-error" />
|
||||
<span className="text-sm text-error">{t("email-status.unsubscribed")}</span>
|
||||
<button className="btn btn-neutral min-h-0 h-[1.5rem]" onClick={ handleResetEmailStatus }>{t("email-status.reset-button-label")}</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
):(
|
||||
<div className="flex items-center gap-2 mt-2 ml-2">
|
||||
<ExclamationTriangleIcon className="h-5 w-5 text-warning" />
|
||||
<span className="text-sm text-warning">{t("email-status.unverified")}</span>
|
||||
<PencilSquareIcon className="h-5 w-5 text-primary" />
|
||||
<span className="text-sm text-primary">{t("email-status.new")}</span>
|
||||
</div>
|
||||
)}
|
||||
<div id="tenantEmail-error" aria-live="polite" aria-atomic="true">
|
||||
|
||||
Reference in New Issue
Block a user