Rename tenantFirstName to tenantName with updated validation

- Renamed tenantFirstName to tenantName in BillingLocation interface
- Updated LocationEditForm field to accept full name (first and last)
- Set maximum length to 30 characters for tenant name field
- Updated all database operations to use tenantName
- Changed English label from "Tenant First Name" to "Tenant First and Last Name"
- Updated Croatian translations to match (Ime i prezime podstanara)
- Updated form validation schema and error messages
- Removed old tenantLastName-related translations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Knee Cola
2025-11-22 22:17:10 +01:00
parent a1c683528c
commit b4e459b2d5
6 changed files with 33 additions and 38 deletions

View File

@@ -15,7 +15,7 @@ export type State = {
errors?: {
locationName?: string[];
generateTenantCode?: string[];
tenantFirstName?: string[];
tenantName?: string[];
tenantStreet?: string[];
tenantTown?: string[];
autoBillFwd?: string[];
@@ -36,7 +36,7 @@ const FormSchema = (t:IntlTemplateFn) => z.object({
_id: z.string(),
locationName: z.coerce.string().min(1, t("location-name-required")),
generateTenantCode: z.boolean().optional().nullable(),
tenantFirstName: z.string().optional().nullable(),
tenantName: z.string().max(30).optional().nullable(),
tenantStreet: z.string().max(27).optional().nullable(),
tenantTown: z.string().max(27).optional().nullable(),
autoBillFwd: z.boolean().optional().nullable(),
@@ -53,12 +53,12 @@ const FormSchema = (t:IntlTemplateFn) => z.object({
// Add conditional validation: if generateTenantCode is true, tenant fields are required
.refine((data) => {
if (data.generateTenantCode) {
return !!data.tenantFirstName && data.tenantFirstName.trim().length > 0;
return !!data.tenantName && data.tenantName.trim().length > 0;
}
return true;
}, {
message: t("tenant-first-name-required"),
path: ["tenantFirstName"],
message: t("tenant-name-required"),
path: ["tenantName"],
})
.refine((data) => {
if (data.generateTenantCode) {
@@ -113,7 +113,7 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
const validatedFields = FormSchema(t).safeParse({
locationName: formData.get('locationName'),
generateTenantCode: formData.get('generateTenantCode') === 'on',
tenantFirstName: formData.get('tenantFirstName') || null,
tenantName: formData.get('tenantName') || null,
tenantStreet: formData.get('tenantStreet') || null,
tenantTown: formData.get('tenantTown') || null,
autoBillFwd: formData.get('autoBillFwd') === 'on',
@@ -137,7 +137,7 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
const {
locationName,
generateTenantCode,
tenantFirstName,
tenantName,
tenantStreet,
tenantTown,
autoBillFwd,
@@ -179,7 +179,7 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
$set: {
name: locationName,
generateTenantCode: generateTenantCode || false,
tenantFirstName: tenantFirstName || null,
tenantName: tenantName || null,
tenantStreet: tenantStreet || null,
tenantTown: tenantTown || null,
autoBillFwd: autoBillFwd || false,
@@ -209,7 +209,7 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
$set: {
name: locationName,
generateTenantCode: generateTenantCode || false,
tenantFirstName: tenantFirstName || null,
tenantName: tenantName || null,
tenantStreet: tenantStreet || null,
tenantTown: tenantTown || null,
autoBillFwd: autoBillFwd || false,
@@ -232,7 +232,7 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
$set: {
name: locationName,
generateTenantCode: generateTenantCode || false,
tenantFirstName: tenantFirstName || null,
tenantName: tenantName || null,
tenantStreet: tenantStreet || null,
tenantTown: tenantTown || null,
autoBillFwd: autoBillFwd || false,
@@ -254,7 +254,7 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
name: locationName,
notes: null,
generateTenantCode: generateTenantCode || false,
tenantFirstName: tenantFirstName || null,
tenantName: tenantName || null,
tenantStreet: tenantStreet || null,
tenantTown: tenantTown || null,
autoBillFwd: autoBillFwd || false,
@@ -328,7 +328,7 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
name: locationName,
notes: null,
generateTenantCode: generateTenantCode || false,
tenantFirstName: tenantFirstName || null,
tenantName: tenantName || null,
tenantStreet: tenantStreet || null,
tenantTown: tenantTown || null,
autoBillFwd: autoBillFwd || false,

View File

@@ -51,8 +51,8 @@ export interface BillingLocation {
notes: string|null;
/** (optional) whether to generate 2D code for tenant */
generateTenantCode?: boolean | null;
/** (optional) tenant first name */
tenantFirstName?: string | null;
/** (optional) tenant name */
tenantName?: string | null;
/** (optional) tenant street */
tenantStreet?: string | null;
/** (optional) tenant town */

View File

@@ -45,7 +45,7 @@ export const LocationEditForm: FC<LocationEditFormProps> = ({ location, yearMont
// Track tenant field values for real-time validation
const [tenantFields, setTenantFields] = useState({
tenantFirstName: location?.tenantFirstName ?? "",
tenantName: location?.tenantName ?? "",
tenantStreet: location?.tenantStreet ?? "",
tenantTown: location?.tenantTown ?? "",
tenantEmail: location?.tenantEmail ?? "",
@@ -101,20 +101,21 @@ export const LocationEditForm: FC<LocationEditFormProps> = ({ location, yearMont
<>
<div className="form-control w-full">
<label className="label">
<span className="label-text">{t("tenant-first-name-label")}</span>
<span className="label-text">{t("tenant-name-label")}</span>
</label>
<input
id="tenantFirstName"
name="tenantFirstName"
id="tenantName"
name="tenantName"
type="text"
placeholder={t("tenant-first-name-placeholder")}
maxLength={30}
placeholder={t("tenant-name-placeholder")}
className="input input-bordered w-full placeholder:text-gray-600"
defaultValue={location?.tenantFirstName ?? ""}
onChange={(e) => handleTenantFieldChange("tenantFirstName", e.target.value)}
defaultValue={location?.tenantName ?? ""}
onChange={(e) => handleTenantFieldChange("tenantName", e.target.value)}
/>
<div id="tenantFirstName-error" aria-live="polite" aria-atomic="true">
{state.errors?.tenantFirstName &&
state.errors.tenantFirstName.map((error: string) => (
<div id="tenantName-error" aria-live="polite" aria-atomic="true">
{state.errors?.tenantName &&
state.errors.tenantName.map((error: string) => (
<p className="mt-2 text-sm text-red-500" key={error}>
{error}
</p>

View File

@@ -16,7 +16,7 @@ export interface ViewLocationCardProps {
export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettings}) => {
const { _id, name, yearMonth, bills, tenantFirstName, tenantStreet, tenantTown } = location;
const { _id, name, yearMonth, bills, tenantName, tenantStreet, tenantTown } = location;
const t = useTranslations("home-page.location-card");
@@ -25,7 +25,7 @@ export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettin
const paymentParams:PaymentParams = {
Iznos: (monthlyExpense/100).toFixed(2).replace(".",","),
ImePlatitelja: tenantFirstName ?? "",
ImePlatitelja: tenantName ?? "",
AdresaPlatitelja: tenantStreet ?? "",
SjedistePlatitelja: tenantTown ?? "",
Primatelj: (userSettings?.firstName && userSettings?.lastName) ? `${userSettings.firstName} ${userSettings.lastName}` : "",