- Auth: TOTP replay protection with counter tracking, constant-time backup code comparison, atomic lockout increment, per-token logout - Invoices/PDFs: net-based VAT calculation, dangerous URL scheme stripping in cleanQuillHtml, orders-pdf error handling - Orders: reject item changes on status transition, cascading delete cleanup, take:1 with orderBy - Projects: atomic rename collision handling, MIME/extension validation, empty customer name rejection - Attendance: Czech public holiday awareness in frontend fund calculation, leave_hours 0 handling, invalid date NaN guard, bounded per-month queries in workfund - Users/Admin: profile audit logging + password validation, session revocation guard, session ID validation, dashboard DB aggregation, soft-deleted record protection in scope templates - Frontend: FormField label linkage, Pagination ARIA, error handling in OrderConfirmationModal, 401 propagation, GPS emoji hidden from screen readers, table sort state fix, geolocation race/abort cleanup, Leaflet popup DOM safety, Vehicles toggleActive minimal body, CompanySettings ref mutation fix, OfferDetail unlock abort, AttendanceBalances combined fetches - Utils: env validation, Puppeteer concurrency mutex, invoice alert cron cleanup on shutdown, body limit alignment, TOTP error logging, trustProxy from env, symlink rejection, rate cache Map usage Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
44 lines
1.0 KiB
TypeScript
44 lines
1.0 KiB
TypeScript
import {
|
|
type CSSProperties,
|
|
type ReactNode,
|
|
isValidElement,
|
|
cloneElement,
|
|
useId,
|
|
} from "react";
|
|
|
|
interface FormFieldProps {
|
|
label: ReactNode;
|
|
children: ReactNode;
|
|
error?: string;
|
|
required?: boolean;
|
|
style?: React.CSSProperties;
|
|
}
|
|
|
|
export default function FormField({
|
|
label,
|
|
children,
|
|
error,
|
|
required,
|
|
style,
|
|
}: FormFieldProps) {
|
|
const generatedId = useId();
|
|
const childProps = isValidElement(children)
|
|
? (children.props as Record<string, unknown>)
|
|
: null;
|
|
const childId = childProps?.id ? String(childProps.id) : generatedId;
|
|
const childWithId = isValidElement(children)
|
|
? cloneElement(children, { id: childId } as React.Attributes)
|
|
: children;
|
|
|
|
return (
|
|
<div className="admin-form-group" style={style}>
|
|
<label className="admin-form-label" htmlFor={childId}>
|
|
{label}
|
|
{required && <span className="admin-form-required"> *</span>}
|
|
</label>
|
|
{childWithId}
|
|
{error && <span className="admin-form-error">{error}</span>}
|
|
</div>
|
|
);
|
|
}
|