fix: react-doctor → 64/100 — add sizes to 12 next/image, add htmlFor/id to 202 label/input pairs, add aria-label to 5 icon links
This commit is contained in:
@@ -248,10 +248,8 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
</div>
|
||||
{provider === "openai" && (
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">
|
||||
Organization ID (optional)
|
||||
</label>
|
||||
<input aria-label="Org ..."
|
||||
<label htmlFor="fld-1-organization-id-optional" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Organization ID (optional)</label>
|
||||
<input id="fld-1-organization-id-optional" aria-label="Org ..."
|
||||
type="text"
|
||||
value={orgId}
|
||||
onChange={(e) => setOrgId(e.target.value)}
|
||||
@@ -293,8 +291,8 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Base URL</label>
|
||||
<input aria-label="Https://api.openai.com/v1 Or Http://localhost:11434/v1"
|
||||
<label htmlFor="fld-2-base-url" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Base URL</label>
|
||||
<input id="fld-2-base-url" aria-label="Https://api.openai.com/v1 Or Http://localhost:11434/v1"
|
||||
type="text"
|
||||
value={customEndpoint}
|
||||
onChange={(e) => setCustomEndpoint(e.target.value)}
|
||||
|
||||
@@ -118,8 +118,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
)}
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Venue name *</label>
|
||||
<input aria-label="Tractor Supply"
|
||||
<label htmlFor="fld-1-venue-name" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Venue name *</label>
|
||||
<input id="fld-1-venue-name" aria-label="Tractor Supply"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
@@ -133,8 +133,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Street address</label>
|
||||
<input aria-label="13778 E I 25 Frontage Rd"
|
||||
<label htmlFor="fld-2-street-address" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Street address</label>
|
||||
<input id="fld-2-street-address" aria-label="13778 E I 25 Frontage Rd"
|
||||
type="text"
|
||||
value={address}
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
@@ -148,8 +148,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
|
||||
<div className="grid grid-cols-6 gap-4">
|
||||
<div className="col-span-3 space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">City</label>
|
||||
<input aria-label="Wellington"
|
||||
<label htmlFor="fld-3-city" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">City</label>
|
||||
<input id="fld-3-city" aria-label="Wellington"
|
||||
type="text"
|
||||
value={city}
|
||||
onChange={(e) => setCity(e.target.value)}
|
||||
@@ -161,8 +161,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1 space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">State</label>
|
||||
<input aria-label="CO"
|
||||
<label htmlFor="fld-4-state" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">State</label>
|
||||
<input id="fld-4-state" aria-label="CO"
|
||||
type="text"
|
||||
value={stateVal}
|
||||
onChange={(e) => setStateVal(e.target.value.toUpperCase())}
|
||||
@@ -175,8 +175,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2 space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">ZIP</label>
|
||||
<input aria-label="80549"
|
||||
<label htmlFor="fld-5-zip" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">ZIP</label>
|
||||
<input id="fld-5-zip" aria-label="80549"
|
||||
type="text"
|
||||
value={zip}
|
||||
onChange={(e) => setZip(e.target.value)}
|
||||
@@ -191,8 +191,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Phone</label>
|
||||
<input aria-label="(970) 555 1234"
|
||||
<label htmlFor="fld-6-phone" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Phone</label>
|
||||
<input id="fld-6-phone" aria-label="(970) 555 1234"
|
||||
type="tel"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
@@ -204,8 +204,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact name</label>
|
||||
<input aria-label="Store Manager"
|
||||
<label htmlFor="fld-7-contact-name" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact name</label>
|
||||
<input id="fld-7-contact-name" aria-label="Store Manager"
|
||||
type="text"
|
||||
value={contactName}
|
||||
onChange={(e) => setContactName(e.target.value)}
|
||||
@@ -219,8 +219,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact email</label>
|
||||
<input aria-label="Manager@example.com"
|
||||
<label htmlFor="fld-8-contact-email" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact email</label>
|
||||
<input id="fld-8-contact-email" aria-label="Manager@example.com"
|
||||
type="email"
|
||||
value={contactEmail}
|
||||
onChange={(e) => setContactEmail(e.target.value)}
|
||||
@@ -233,8 +233,8 @@ export default function AddLocationModal({ isOpen, onClose, brandId, onSuccess }
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Notes</label>
|
||||
<textarea aria-label="Park On West Side. Use Side Entrance After 9am."
|
||||
<label htmlFor="fld-9-notes" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Notes</label>
|
||||
<textarea id="fld-9-notes" aria-label="Park On West Side. Use Side Entrance After 9am."
|
||||
value={notes}
|
||||
onChange={(e) => setNotes(e.target.value)}
|
||||
placeholder="Park on west side. Use side entrance after 9am."
|
||||
|
||||
@@ -221,8 +221,8 @@ export default function AdvancedIntegrations({ brandId, brands }: Props) {
|
||||
</div>
|
||||
{/* From Email */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">From Email</label>
|
||||
<input aria-label="Orders@yourbrand.com"
|
||||
<label htmlFor="fld-1-from-email" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">From Email</label>
|
||||
<input id="fld-1-from-email" aria-label="Orders@yourbrand.com"
|
||||
type="email"
|
||||
value={credentials.resend.from_email}
|
||||
onChange={(e) => setCredentials((p) => ({
|
||||
@@ -235,8 +235,8 @@ export default function AdvancedIntegrations({ brandId, brands }: Props) {
|
||||
</div>
|
||||
{/* From Name */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">From Name</label>
|
||||
<input aria-label="Your Brand Name"
|
||||
<label htmlFor="fld-2-from-name" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">From Name</label>
|
||||
<input id="fld-2-from-name" aria-label="Your Brand Name"
|
||||
type="text"
|
||||
value={credentials.resend.from_name}
|
||||
onChange={(e) => setCredentials((p) => ({
|
||||
@@ -293,8 +293,8 @@ export default function AdvancedIntegrations({ brandId, brands }: Props) {
|
||||
<div className="p-4 sm:p-6 space-y-4">
|
||||
{/* Account SID */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Account SID</label>
|
||||
<input aria-label="AC..."
|
||||
<label htmlFor="fld-3-account-sid" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Account SID</label>
|
||||
<input id="fld-3-account-sid" aria-label="AC..."
|
||||
type="text"
|
||||
value={credentials.twilio.account_sid}
|
||||
onChange={(e) => setCredentials((p) => ({
|
||||
@@ -330,8 +330,8 @@ export default function AdvancedIntegrations({ brandId, brands }: Props) {
|
||||
</div>
|
||||
{/* Phone Number */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Phone Number</label>
|
||||
<input aria-label="+1234567890"
|
||||
<label htmlFor="fld-4-phone-number" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Phone Number</label>
|
||||
<input id="fld-4-phone-number" aria-label="+1234567890"
|
||||
type="tel"
|
||||
value={credentials.twilio.phone_number}
|
||||
onChange={(e) => setCredentials((p) => ({
|
||||
|
||||
@@ -105,8 +105,8 @@ export default function AdvancedShipping({ brandId }: { brandId: string }) {
|
||||
<div className="p-4 sm:p-6 space-y-4">
|
||||
{/* Carrier Selection */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Carrier</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-1-carrier" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Carrier</label>
|
||||
<select id="fld-1-carrier" aria-label="Select"
|
||||
value={carrier}
|
||||
onChange={(e) => setCarrier(e.target.value)}
|
||||
className="w-full sm:w-auto rounded-lg border border-[var(--admin-border)] bg-white px-4 py-2.5 text-sm text-[var(--admin-text-primary)] outline-none focus:border-emerald-500 focus:ring-1 focus:ring-emerald-500"
|
||||
@@ -120,8 +120,8 @@ export default function AdvancedShipping({ brandId }: { brandId: string }) {
|
||||
|
||||
{/* Account Number */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Account Number</label>
|
||||
<input aria-label="Enter Account Number"
|
||||
<label htmlFor="fld-2-account-number" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Account Number</label>
|
||||
<input id="fld-2-account-number" aria-label="Enter Account Number"
|
||||
type="text"
|
||||
value={accountNumber}
|
||||
onChange={(e) => setAccountNumber(e.target.value)}
|
||||
|
||||
@@ -96,8 +96,8 @@ export default function AdvancedSquareSync({ brandId }: { brandId: string }) {
|
||||
<div className="p-4 sm:p-6 space-y-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Application ID</label>
|
||||
<input aria-label="Sq0idp ..."
|
||||
<label htmlFor="fld-1-application-id" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Application ID</label>
|
||||
<input id="fld-1-application-id" aria-label="Sq0idp ..."
|
||||
type="password"
|
||||
value={appId}
|
||||
onChange={(e) => setAppId(e.target.value)}
|
||||
@@ -106,8 +106,8 @@ export default function AdvancedSquareSync({ brandId }: { brandId: string }) {
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Access Token</label>
|
||||
<input aria-label="EAAAl..."
|
||||
<label htmlFor="fld-2-access-token" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Access Token</label>
|
||||
<input id="fld-2-access-token" aria-label="EAAAl..."
|
||||
type="password"
|
||||
value={accessToken}
|
||||
onChange={(e) => setAccessToken(e.target.value)}
|
||||
@@ -116,8 +116,8 @@ export default function AdvancedSquareSync({ brandId }: { brandId: string }) {
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Location ID</label>
|
||||
<input aria-label="L..."
|
||||
<label htmlFor="fld-3-location-id" className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Location ID</label>
|
||||
<input id="fld-3-location-id" aria-label="L..."
|
||||
type="text"
|
||||
value={locationId}
|
||||
onChange={(e) => setLocationId(e.target.value)}
|
||||
|
||||
@@ -147,10 +147,8 @@ function NewCampaignModal({
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">
|
||||
Campaign Name *
|
||||
</label>
|
||||
<input aria-label=". Weekly Pickup Reminder"
|
||||
<label htmlFor="fld-1-campaign-name" className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Name *</label>
|
||||
<input id="fld-1-campaign-name" aria-label=". Weekly Pickup Reminder"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
@@ -161,10 +159,8 @@ function NewCampaignModal({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">
|
||||
Campaign Type *
|
||||
</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-2-campaign-type" className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Type *</label>
|
||||
<select id="fld-2-campaign-type" aria-label="Select"
|
||||
value={campaignType}
|
||||
onChange={(e) => setCampaignType(e.target.value as CampaignType)}
|
||||
className="w-full border border-[var(--admin-border)] rounded-lg px-3 py-2.5 text-sm bg-white text-[var(--admin-text-primary)] focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none"
|
||||
@@ -504,8 +500,8 @@ export function CampaignEditPanel({
|
||||
<div className="rounded-xl border border-[var(--admin-border)] bg-white p-4 sm:p-6 space-y-4">
|
||||
<h3 className="text-xs sm:text-sm font-semibold text-[var(--admin-text-muted)] uppercase tracking-wide">Basic Info</h3>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Name *</label>
|
||||
<input aria-label=". Tuxedo Stop 5/15 Reminder"
|
||||
<label htmlFor="fld-3-campaign-name-2" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Name *</label>
|
||||
<input id="fld-3-campaign-name-2" aria-label=". Tuxedo Stop 5/15 Reminder"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
@@ -515,8 +511,8 @@ export function CampaignEditPanel({
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Type *</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-4-campaign-type-2" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Type *</label>
|
||||
<select id="fld-4-campaign-type-2" aria-label="Select"
|
||||
value={campaignType}
|
||||
onChange={(e) => setCampaignType(e.target.value as CampaignType)}
|
||||
className="w-full border border-[var(--admin-border)] rounded-lg px-3 py-2 text-sm bg-white text-[var(--admin-text-primary)]"
|
||||
@@ -527,8 +523,8 @@ export function CampaignEditPanel({
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-5-template" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template</label>
|
||||
<select id="fld-5-template" aria-label="Select"
|
||||
value={templateId}
|
||||
onChange={(e) => {
|
||||
setTemplateId(e.target.value);
|
||||
@@ -567,8 +563,8 @@ export function CampaignEditPanel({
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Target By</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-6-target-by" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Target By</label>
|
||||
<select id="fld-6-target-by" aria-label="Select"
|
||||
value={audienceTarget}
|
||||
onChange={(e) => {
|
||||
setAudienceTarget(e.target.value);
|
||||
@@ -585,8 +581,8 @@ export function CampaignEditPanel({
|
||||
{audienceTarget === "stop" && (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Stop ID</label>
|
||||
<input aria-label="UUID"
|
||||
<label htmlFor="fld-7-stop-id" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Stop ID</label>
|
||||
<input id="fld-7-stop-id" aria-label="UUID"
|
||||
type="text"
|
||||
value={stopId}
|
||||
onChange={(e) => setStopId(e.target.value)}
|
||||
@@ -595,8 +591,8 @@ export function CampaignEditPanel({
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">From</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-8-from" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">From</label>
|
||||
<input id="fld-8-from" aria-label="Date"
|
||||
type="date"
|
||||
value={dateFrom}
|
||||
onChange={(e) => setDateFrom(e.target.value)}
|
||||
@@ -604,8 +600,8 @@ export function CampaignEditPanel({
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">To</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-9-to" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">To</label>
|
||||
<input id="fld-9-to" aria-label="Date"
|
||||
type="date"
|
||||
value={dateTo}
|
||||
onChange={(e) => setDateTo(e.target.value)}
|
||||
@@ -638,8 +634,8 @@ export function CampaignEditPanel({
|
||||
<div className="rounded-xl border border-[var(--admin-border)] bg-white p-4 sm:p-6 space-y-4">
|
||||
<h3 className="text-xs sm:text-sm font-semibold text-[var(--admin-text-muted)] uppercase tracking-wide">Message Content</h3>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Subject</label>
|
||||
<input aria-label="Email Subject Line"
|
||||
<label htmlFor="fld-10-subject" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Subject</label>
|
||||
<input id="fld-10-subject" aria-label="Email Subject Line"
|
||||
type="text"
|
||||
value={subject}
|
||||
onChange={(e) => setSubject(e.target.value)}
|
||||
@@ -648,8 +644,8 @@ export function CampaignEditPanel({
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Body (Plain Text)</label>
|
||||
<textarea aria-label="Message Content..."
|
||||
<label htmlFor="fld-11-body-plain-text" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Body (Plain Text)</label>
|
||||
<textarea id="fld-11-body-plain-text" aria-label="Message Content..."
|
||||
value={bodyText}
|
||||
onChange={(e) => setBodyText(e.target.value)}
|
||||
rows={6}
|
||||
@@ -684,8 +680,8 @@ export function CampaignEditPanel({
|
||||
</div>
|
||||
{scheduleMode === "later" && (
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Send date & time</label>
|
||||
<input aria-label="Datetime Local"
|
||||
<label htmlFor="fld-12-send-date-time" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Send date & time</label>
|
||||
<input id="fld-12-send-date-time" aria-label="Datetime Local"
|
||||
type="datetime-local"
|
||||
value={scheduledAt}
|
||||
onChange={(e) => setScheduledAt(e.target.value)}
|
||||
|
||||
@@ -140,8 +140,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
)}
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Venue name *</label>
|
||||
<input aria-label="Text"
|
||||
<label htmlFor="fld-1-venue-name" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Venue name *</label>
|
||||
<input id="fld-1-venue-name" aria-label="Text"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
@@ -154,8 +154,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Street address</label>
|
||||
<input aria-label="Text"
|
||||
<label htmlFor="fld-2-street-address" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Street address</label>
|
||||
<input id="fld-2-street-address" aria-label="Text"
|
||||
type="text"
|
||||
value={address}
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
@@ -168,8 +168,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
|
||||
<div className="grid grid-cols-6 gap-4">
|
||||
<div className="col-span-3 space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">City</label>
|
||||
<input aria-label="Text"
|
||||
<label htmlFor="fld-3-city" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">City</label>
|
||||
<input id="fld-3-city" aria-label="Text"
|
||||
type="text"
|
||||
value={city}
|
||||
onChange={(e) => setCity(e.target.value)}
|
||||
@@ -180,8 +180,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1 space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">State</label>
|
||||
<input aria-label="Text"
|
||||
<label htmlFor="fld-4-state" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">State</label>
|
||||
<input id="fld-4-state" aria-label="Text"
|
||||
type="text"
|
||||
value={stateVal}
|
||||
onChange={(e) => setStateVal(e.target.value.toUpperCase())}
|
||||
@@ -193,8 +193,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2 space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">ZIP</label>
|
||||
<input aria-label="Text"
|
||||
<label htmlFor="fld-5-zip" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">ZIP</label>
|
||||
<input id="fld-5-zip" aria-label="Text"
|
||||
type="text"
|
||||
value={zip}
|
||||
onChange={(e) => setZip(e.target.value)}
|
||||
@@ -208,8 +208,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Phone</label>
|
||||
<input aria-label="Tel"
|
||||
<label htmlFor="fld-6-phone" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Phone</label>
|
||||
<input id="fld-6-phone" aria-label="Tel"
|
||||
type="tel"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
@@ -220,8 +220,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact name</label>
|
||||
<input aria-label="Text"
|
||||
<label htmlFor="fld-7-contact-name" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact name</label>
|
||||
<input id="fld-7-contact-name" aria-label="Text"
|
||||
type="text"
|
||||
value={contactName}
|
||||
onChange={(e) => setContactName(e.target.value)}
|
||||
@@ -234,8 +234,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact email</label>
|
||||
<input aria-label="Email"
|
||||
<label htmlFor="fld-8-contact-email" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Contact email</label>
|
||||
<input id="fld-8-contact-email" aria-label="Email"
|
||||
type="email"
|
||||
value={contactEmail}
|
||||
onChange={(e) => setContactEmail(e.target.value)}
|
||||
@@ -247,8 +247,8 @@ export default function EditLocationModal({ isOpen, onClose, location, brandId,
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Notes</label>
|
||||
<textarea aria-label="Textarea"
|
||||
<label htmlFor="fld-9-notes" className="block text-xs font-medium text-stone-500 uppercase tracking-wide ml-1">Notes</label>
|
||||
<textarea id="fld-9-notes" aria-label="Textarea"
|
||||
value={notes}
|
||||
onChange={(e) => setNotes(e.target.value)}
|
||||
rows={2}
|
||||
|
||||
@@ -519,8 +519,8 @@ export default function CampaignComposerPage({ brandId, campaigns, templates, se
|
||||
{/* Editor */}
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-stone-700 mb-1.5">Subject Line</label>
|
||||
<input aria-label="Enter A Compelling Subject..."
|
||||
<label htmlFor="fld-1-subject-line" className="block text-sm font-semibold text-stone-700 mb-1.5">Subject Line</label>
|
||||
<input id="fld-1-subject-line" aria-label="Enter A Compelling Subject..."
|
||||
type="text"
|
||||
placeholder="Enter a compelling subject..."
|
||||
value={subject}
|
||||
@@ -531,8 +531,8 @@ export default function CampaignComposerPage({ brandId, campaigns, templates, se
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-stone-700 mb-1.5">Message Body</label>
|
||||
<textarea aria-label="Write Your Message Here..."
|
||||
<label htmlFor="fld-2-message-body" className="block text-sm font-semibold text-stone-700 mb-1.5">Message Body</label>
|
||||
<textarea id="fld-2-message-body" aria-label="Write Your Message Here..."
|
||||
placeholder="Write your message here..."
|
||||
value={bodyText}
|
||||
onChange={(e) => setBodyText(e.target.value)}
|
||||
@@ -596,8 +596,8 @@ export default function CampaignComposerPage({ brandId, campaigns, templates, se
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-stone-700 mb-1.5">Recipient Segment</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-3-recipient-segment" className="block text-sm font-semibold text-stone-700 mb-1.5">Recipient Segment</label>
|
||||
<select id="fld-3-recipient-segment" aria-label="Select"
|
||||
value={selectedSegmentId}
|
||||
onChange={(e) => setSelectedSegmentId(e.target.value)}
|
||||
className="w-full border border-stone-200 rounded-xl px-4 py-3 text-sm bg-white outline-none focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 transition-all"
|
||||
@@ -791,8 +791,8 @@ export default function CampaignComposerPage({ brandId, campaigns, templates, se
|
||||
|
||||
{!sendNow && (
|
||||
<div className="mt-4">
|
||||
<label className="block text-sm font-semibold text-stone-700 mb-1.5">Send Date & Time</label>
|
||||
<input aria-label="Datetime Local"
|
||||
<label htmlFor="fld-4-send-date-time" className="block text-sm font-semibold text-stone-700 mb-1.5">Send Date & Time</label>
|
||||
<input id="fld-4-send-date-time" aria-label="Datetime Local"
|
||||
type="datetime-local"
|
||||
value={scheduledAt}
|
||||
onChange={(e) => setScheduledAt(e.target.value)}
|
||||
|
||||
@@ -327,8 +327,8 @@ function FilterBlock({ brandId, filter, onChange, onRemove }: FilterBlockProps)
|
||||
</select>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="text-xs text-[var(--admin-text-muted)] mb-1 block">From</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-1-from" className="text-xs text-[var(--admin-text-muted)] mb-1 block">From</label>
|
||||
<input id="fld-1-from" aria-label="Date"
|
||||
type="date"
|
||||
value={filter.params.date_from ?? ""}
|
||||
onChange={(e) => onChange({ params: { ...filter.params, date_from: e.target.value } })}
|
||||
@@ -336,8 +336,8 @@ function FilterBlock({ brandId, filter, onChange, onRemove }: FilterBlockProps)
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs text-[var(--admin-text-muted)] mb-1 block">To</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-2-to" className="text-xs text-[var(--admin-text-muted)] mb-1 block">To</label>
|
||||
<input id="fld-2-to" aria-label="Date"
|
||||
type="date"
|
||||
value={filter.params.date_to ?? ""}
|
||||
onChange={(e) => onChange({ params: { ...filter.params, date_to: e.target.value } })}
|
||||
@@ -366,8 +366,8 @@ function FilterBlock({ brandId, filter, onChange, onRemove }: FilterBlockProps)
|
||||
))}
|
||||
</select>
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] whitespace-nowrap">In the last</label>
|
||||
<input aria-label="Number"
|
||||
<label htmlFor="fld-3-in-the-last" className="text-xs text-[var(--admin-text-muted)] whitespace-nowrap">In the last</label>
|
||||
<input id="fld-3-in-the-last" aria-label="Number"
|
||||
type="number"
|
||||
min={1}
|
||||
max={365}
|
||||
@@ -422,8 +422,8 @@ function FilterBlock({ brandId, filter, onChange, onRemove }: FilterBlockProps)
|
||||
))}
|
||||
</select>
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] whitespace-nowrap">In the last</label>
|
||||
<input aria-label="Number"
|
||||
<label htmlFor="fld-4-in-the-last-2" className="text-xs text-[var(--admin-text-muted)] whitespace-nowrap">In the last</label>
|
||||
<input id="fld-4-in-the-last-2" aria-label="Number"
|
||||
type="number"
|
||||
min={1}
|
||||
max={365}
|
||||
|
||||
@@ -74,8 +74,8 @@ export default function SegmentEditModal({ initialName = "", initialDescription
|
||||
{/* Content */}
|
||||
<div className="p-6 flex flex-col gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Segment Name</label>
|
||||
<input aria-label=". Fort Pierce Regulars"
|
||||
<label htmlFor="fld-1-segment-name" className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Segment Name</label>
|
||||
<input id="fld-1-segment-name" aria-label=". Fort Pierce Regulars"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
|
||||
@@ -217,10 +217,8 @@ export default function MessageCustomersSection({
|
||||
<form onSubmit={handleSend} className="space-y-4">
|
||||
{showSubject && (
|
||||
<div>
|
||||
<label className="mb-1 block text-sm font-medium text-zinc-300">
|
||||
Subject
|
||||
</label>
|
||||
<input aria-label="Important Update About Your Pickup"
|
||||
<label htmlFor="fld-1-subject" className="mb-1 block text-sm font-medium text-zinc-300">Subject</label>
|
||||
<input id="fld-1-subject" aria-label="Important Update About Your Pickup"
|
||||
type="text"
|
||||
value={subject}
|
||||
onChange={(e) => setSubject(e.target.value)}
|
||||
@@ -231,10 +229,8 @@ export default function MessageCustomersSection({
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label className="mb-1 block text-sm font-medium text-zinc-300">
|
||||
Message
|
||||
</label>
|
||||
<textarea aria-label="Type Your Message Here..."
|
||||
<label htmlFor="fld-2-message" className="mb-1 block text-sm font-medium text-zinc-300">Message</label>
|
||||
<textarea id="fld-2-message" aria-label="Type Your Message Here..."
|
||||
value={body}
|
||||
onChange={(e) => setBody(e.target.value)}
|
||||
rows={4}
|
||||
|
||||
@@ -279,8 +279,8 @@ export default function NewStopForm({ duplicateFrom }: Props) {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-stone-700 mb-1.5">Active</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-1-active" className="block text-xs font-semibold text-stone-700 mb-1.5">Active</label>
|
||||
<select id="fld-1-active" aria-label="Select"
|
||||
value={active}
|
||||
onChange={(e) => setActive(e.target.value)}
|
||||
className="w-full rounded-xl border border-[var(--admin-border)] bg-white px-3 py-2.5 text-sm text-[var(--admin-text-primary)] outline-none focus:border-[var(--admin-accent)] focus:ring-2 focus:ring-[var(--admin-accent)]/20"
|
||||
@@ -292,8 +292,8 @@ export default function NewStopForm({ duplicateFrom }: Props) {
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-stone-700 mb-1.5">Street Address</label>
|
||||
<input aria-label="123 Main St"
|
||||
<label htmlFor="fld-2-street-address" className="block text-xs font-semibold text-stone-700 mb-1.5">Street Address</label>
|
||||
<input id="fld-2-street-address" aria-label="123 Main St"
|
||||
type="text"
|
||||
value={address}
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
@@ -303,8 +303,8 @@ export default function NewStopForm({ duplicateFrom }: Props) {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-stone-700 mb-1.5">ZIP Code</label>
|
||||
<input aria-label="80102"
|
||||
<label htmlFor="fld-3-zip-code" className="block text-xs font-semibold text-stone-700 mb-1.5">ZIP Code</label>
|
||||
<input id="fld-3-zip-code" aria-label="80102"
|
||||
type="text"
|
||||
value={zip}
|
||||
onChange={(e) => setZip(e.target.value)}
|
||||
|
||||
@@ -371,8 +371,8 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
|
||||
<div className="mt-3 grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="ha-field-label mb-1">Qty</label>
|
||||
<input aria-label="Number"
|
||||
<label htmlFor="fld-1-qty" className="ha-field-label mb-1">Qty</label>
|
||||
<input id="fld-1-qty" aria-label="Number"
|
||||
type="number"
|
||||
min="1"
|
||||
value={item.quantity}
|
||||
@@ -461,8 +461,8 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<label className="ha-field-label mb-1.5">Discount Reason</label>
|
||||
<input aria-label="Optional"
|
||||
<label htmlFor="fld-2-discount-reason" className="ha-field-label mb-1.5">Discount Reason</label>
|
||||
<input id="fld-2-discount-reason" aria-label="Optional"
|
||||
type="text"
|
||||
value={discount_reason}
|
||||
onChange={(e) => setDiscount_reason(e.target.value)}
|
||||
|
||||
@@ -170,8 +170,8 @@ export default function OrderPaymentSection({
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="mb-1 block text-xs font-semibold text-stone-500">Processor</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-1-processor" className="mb-1 block text-xs font-semibold text-stone-500">Processor</label>
|
||||
<select id="fld-1-processor" aria-label="Select"
|
||||
value={processor}
|
||||
onChange={(e) => setProcessor(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2.5 text-sm outline-none focus:border-[var(--admin-accent)] focus:ring-2 focus:ring-[var(--admin-accent)]/20"
|
||||
@@ -186,8 +186,8 @@ export default function OrderPaymentSection({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="mb-1 block text-xs font-semibold text-stone-500">Payment Status</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-2-payment-status" className="mb-1 block text-xs font-semibold text-stone-500">Payment Status</label>
|
||||
<select id="fld-2-payment-status" aria-label="Select"
|
||||
value={status}
|
||||
onChange={(e) => setStatus(e.target.value)}
|
||||
className="w-full rounded-xl border border-stone-200 bg-white px-3 py-2.5 text-sm outline-none focus:border-[var(--admin-accent)] focus:ring-2 focus:ring-[var(--admin-accent)]/20"
|
||||
@@ -202,8 +202,8 @@ export default function OrderPaymentSection({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="mb-1 block text-xs font-semibold text-stone-500">Transaction ID</label>
|
||||
<input aria-label="External Payment Reference"
|
||||
<label htmlFor="fld-3-transaction-id" className="mb-1 block text-xs font-semibold text-stone-500">Transaction ID</label>
|
||||
<input id="fld-3-transaction-id" aria-label="External Payment Reference"
|
||||
type="text"
|
||||
value={transactionId}
|
||||
onChange={(e) => setTransactionId(e.target.value)}
|
||||
@@ -300,8 +300,8 @@ export default function OrderPaymentSection({
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<label className="mb-1 block text-xs font-semibold text-stone-500">Reason</label>
|
||||
<input aria-label="Customer Request, Defective Product, Etc."
|
||||
<label htmlFor="fld-4-reason" className="mb-1 block text-xs font-semibold text-stone-500">Reason</label>
|
||||
<input id="fld-4-reason" aria-label="Customer Request, Defective Product, Etc."
|
||||
type="text"
|
||||
value={refundReason}
|
||||
onChange={(e) => setRefundReason(e.target.value)}
|
||||
|
||||
@@ -359,6 +359,7 @@ export default function ProductFormModal({
|
||||
src={imagePreview}
|
||||
alt="Product preview"
|
||||
fill
|
||||
sizes="(max-width: 640px) 100vw, 50vw"
|
||||
style={{ objectFit: "contain" }}
|
||||
className="rounded-md"
|
||||
/>
|
||||
|
||||
@@ -160,6 +160,7 @@ function ProductRowBase({
|
||||
src={product.image_url}
|
||||
alt={product.name}
|
||||
fill
|
||||
sizes="48px"
|
||||
style={{ objectFit: "cover" }}
|
||||
onError={(e) => { (e.target as HTMLImageElement).style.display = "none"; }}
|
||||
/>
|
||||
|
||||
@@ -462,6 +462,7 @@ function TableView({
|
||||
src={product.image_url}
|
||||
alt={product.name}
|
||||
fill
|
||||
sizes="40px"
|
||||
style={{ objectFit: "cover" }}
|
||||
onError={(e) => { (e.target as HTMLImageElement).style.display = "none"; }}
|
||||
/>
|
||||
@@ -623,6 +624,7 @@ function CardView({
|
||||
src={product.image_url}
|
||||
alt={product.name}
|
||||
fill
|
||||
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
|
||||
style={{ objectFit: "cover" }}
|
||||
className="transition-transform group-hover:scale-105"
|
||||
onError={(e) => { (e.target as HTMLImageElement).style.display = "none"; }}
|
||||
|
||||
@@ -323,8 +323,8 @@ export default function SettingsSections({ brandId, workersOnly, tasksOnly }: Pr
|
||||
<h3 className="text-sm font-semibold text-stone-800 mb-4">Pay Period & Overtime</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-2">Work week starts on</label>
|
||||
<select aria-label="Select" value={payPeriodStartDay} onChange={e => setPayPeriodStartDay(Number(e.target.value))}
|
||||
<label htmlFor="fld-1-work-week-starts-on" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-2">Work week starts on</label>
|
||||
<select id="fld-1-work-week-starts-on" aria-label="Select" value={payPeriodStartDay} onChange={e => setPayPeriodStartDay(Number(e.target.value))}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 focus:outline-none focus:border-emerald-500 transition-colors">
|
||||
{DAYS.map((d, i) => <option key={d} value={i}>{d}</option>)}
|
||||
</select>
|
||||
@@ -630,23 +630,23 @@ export default function SettingsSections({ brandId, workersOnly, tasksOnly }: Pr
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Name *</label>
|
||||
<input aria-label="Worker Name" value={workerName} onChange={e => setWorkerName(e.target.value)}
|
||||
<label htmlFor="fld-2-name" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Name *</label>
|
||||
<input id="fld-2-name" aria-label="Worker Name" value={workerName} onChange={e => setWorkerName(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 placeholder:text-stone-400 focus:outline-none focus:border-emerald-500 transition-colors"
|
||||
placeholder="Worker name" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Role</label>
|
||||
<select aria-label="Select" value={workerRole} onChange={e => setWorkerRole(e.target.value)}
|
||||
<label htmlFor="fld-3-role" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Role</label>
|
||||
<select id="fld-3-role" aria-label="Select" value={workerRole} onChange={e => setWorkerRole(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 focus:outline-none focus:border-emerald-500 transition-colors">
|
||||
<option value="worker">Worker</option>
|
||||
<option value="time_admin">Time Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Lang</label>
|
||||
<select aria-label="Select" value={workerLang} onChange={e => setWorkerLang(e.target.value)}
|
||||
<label htmlFor="fld-4-lang" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Lang</label>
|
||||
<select id="fld-4-lang" aria-label="Select" value={workerLang} onChange={e => setWorkerLang(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 focus:outline-none focus:border-emerald-500 transition-colors">
|
||||
<option value="en">English</option>
|
||||
<option value="es">Español</option>
|
||||
@@ -695,21 +695,21 @@ export default function SettingsSections({ brandId, workersOnly, tasksOnly }: Pr
|
||||
<div className="p-6 space-y-4">
|
||||
{taskError && <div className="bg-red-50 border border-red-200 rounded-xl py-3 px-4 text-red-700 text-sm">{taskError}</div>}
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Name (EN) *</label>
|
||||
<input aria-label=". Harvesting" value={taskName} onChange={e => setTaskName(e.target.value)}
|
||||
<label htmlFor="fld-5-name-en" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Name (EN) *</label>
|
||||
<input id="fld-5-name-en" aria-label=". Harvesting" value={taskName} onChange={e => setTaskName(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 placeholder:text-stone-400 focus:outline-none focus:border-emerald-500 transition-colors"
|
||||
placeholder="e.g. Harvesting" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Name (ES)</label>
|
||||
<input aria-label=". Cosecha" value={taskNameEs} onChange={e => setTaskNameEs(e.target.value)}
|
||||
<label htmlFor="fld-6-name-es" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Name (ES)</label>
|
||||
<input id="fld-6-name-es" aria-label=". Cosecha" value={taskNameEs} onChange={e => setTaskNameEs(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 placeholder:text-stone-400 focus:outline-none focus:border-emerald-500 transition-colors"
|
||||
placeholder="e.g. Cosecha" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Unit</label>
|
||||
<select aria-label="Select" value={taskUnit} onChange={e => setTaskUnit(e.target.value)}
|
||||
<label htmlFor="fld-7-unit" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Unit</label>
|
||||
<select id="fld-7-unit" aria-label="Select" value={taskUnit} onChange={e => setTaskUnit(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 focus:outline-none focus:border-emerald-500 transition-colors">
|
||||
<option value="hours">Hours</option>
|
||||
<option value="pieces">Pieces</option>
|
||||
@@ -717,8 +717,8 @@ export default function SettingsSections({ brandId, workersOnly, tasksOnly }: Pr
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Sort Order</label>
|
||||
<input aria-label="Number" type="number" value={taskSortOrder} onChange={e => setTaskSortOrder(parseInt(e.target.value) || 0)}
|
||||
<label htmlFor="fld-8-sort-order" className="block text-xs font-semibold uppercase tracking-widest text-stone-500 mb-1.5">Sort Order</label>
|
||||
<input id="fld-8-sort-order" aria-label="Number" type="number" value={taskSortOrder} onChange={e => setTaskSortOrder(parseInt(e.target.value) || 0)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-stone-200 bg-white text-stone-900 focus:outline-none focus:border-emerald-500 transition-colors" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -262,8 +262,8 @@ export default function StopEditForm({ stop, brands, onSaved }: StopEditFormProp
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-stone-700 mb-1.5">Time</label>
|
||||
<input aria-label=". 8:00 AM – 2:00 PM"
|
||||
<label htmlFor="fld-1-time" className="block text-xs font-semibold text-stone-700 mb-1.5">Time</label>
|
||||
<input id="fld-1-time" aria-label=". 8:00 AM – 2:00 PM"
|
||||
type="text"
|
||||
value={time}
|
||||
onChange={(e) => setTime(e.target.value)}
|
||||
@@ -274,8 +274,8 @@ export default function StopEditForm({ stop, brands, onSaved }: StopEditFormProp
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-stone-700 mb-1.5">Location Name</label>
|
||||
<input aria-label="Street Address Or Intersection"
|
||||
<label htmlFor="fld-2-location-name" className="block text-xs font-semibold text-stone-700 mb-1.5">Location Name</label>
|
||||
<input id="fld-2-location-name" aria-label="Street Address Or Intersection"
|
||||
type="text"
|
||||
value={location}
|
||||
onChange={(e) => setLocation(e.target.value)}
|
||||
@@ -286,8 +286,8 @@ export default function StopEditForm({ stop, brands, onSaved }: StopEditFormProp
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-stone-700 mb-1.5">Street Address</label>
|
||||
<input aria-label="123 Main St"
|
||||
<label htmlFor="fld-3-street-address" className="block text-xs font-semibold text-stone-700 mb-1.5">Street Address</label>
|
||||
<input id="fld-3-street-address" aria-label="123 Main St"
|
||||
type="text"
|
||||
value={address}
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
@@ -297,8 +297,8 @@ export default function StopEditForm({ stop, brands, onSaved }: StopEditFormProp
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-stone-700 mb-1.5">ZIP Code</label>
|
||||
<input aria-label="80102"
|
||||
<label htmlFor="fld-4-zip-code" className="block text-xs font-semibold text-stone-700 mb-1.5">ZIP Code</label>
|
||||
<input id="fld-4-zip-code" aria-label="80102"
|
||||
type="text"
|
||||
value={zip}
|
||||
onChange={(e) => setZip(e.target.value)}
|
||||
|
||||
@@ -165,10 +165,8 @@ function NewTemplateModal({
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">
|
||||
Template Name *
|
||||
</label>
|
||||
<input aria-label=". Pickup Reminder"
|
||||
<label htmlFor="fld-1-template-name" className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template Name *</label>
|
||||
<input id="fld-1-template-name" aria-label=". Pickup Reminder"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
@@ -179,10 +177,8 @@ function NewTemplateModal({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">
|
||||
Template Type *
|
||||
</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-2-template-type" className="block text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template Type *</label>
|
||||
<select id="fld-2-template-type" aria-label="Select"
|
||||
value={templateType}
|
||||
onChange={(e) => setTemplateType(e.target.value as TemplateType)}
|
||||
className="w-full border border-[var(--admin-border)] rounded-lg px-3 py-2.5 text-sm bg-white text-[var(--admin-text-primary)] focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none"
|
||||
@@ -445,8 +441,8 @@ export function TemplateEditForm({
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template Name *</label>
|
||||
<input aria-label=". Pickup Reminder"
|
||||
<label htmlFor="fld-3-template-name-2" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template Name *</label>
|
||||
<input id="fld-3-template-name-2" aria-label=". Pickup Reminder"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
@@ -456,8 +452,8 @@ export function TemplateEditForm({
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template Type *</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-4-template-type-2" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Template Type *</label>
|
||||
<select id="fld-4-template-type-2" aria-label="Select"
|
||||
value={templateType}
|
||||
onChange={(e) => setTemplateType(e.target.value as TemplateType)}
|
||||
className="w-full border border-[var(--admin-border)] rounded-lg px-3 py-2 text-sm bg-white text-[var(--admin-text-primary)]"
|
||||
@@ -468,8 +464,8 @@ export function TemplateEditForm({
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Type</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-5-campaign-type" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Campaign Type</label>
|
||||
<select id="fld-5-campaign-type" aria-label="Select"
|
||||
value={campaignType}
|
||||
onChange={(e) => setCampaignType(e.target.value as CampaignType)}
|
||||
className="w-full border border-[var(--admin-border)] rounded-lg px-3 py-2 text-sm bg-white text-[var(--admin-text-primary)]"
|
||||
@@ -487,8 +483,8 @@ export function TemplateEditForm({
|
||||
<div className="rounded-xl border border-[var(--admin-border)] bg-white p-4 sm:p-6 space-y-4">
|
||||
<h3 className="text-xs sm:text-sm font-semibold text-[var(--admin-text-muted)] uppercase tracking-wide">Subject Line</h3>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Subject *</label>
|
||||
<input aria-label="Email Subject Line"
|
||||
<label htmlFor="fld-6-subject" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">Subject *</label>
|
||||
<input id="fld-6-subject" aria-label="Email Subject Line"
|
||||
type="text"
|
||||
value={subject}
|
||||
onChange={(e) => setSubject(e.target.value)}
|
||||
@@ -548,8 +544,8 @@ export function TemplateEditForm({
|
||||
{htmlMode ? (
|
||||
<>
|
||||
<div>
|
||||
<label className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">HTML Body</label>
|
||||
<textarea aria-label="<p>HTML Version With Variables Like {{first Name}}...</p>"
|
||||
<label htmlFor="fld-7-html-body" className="block text-xs sm:text-sm font-medium text-[var(--admin-text-primary)] mb-1.5">HTML Body</label>
|
||||
<textarea id="fld-7-html-body" aria-label="<p>HTML Version With Variables Like {{first Name}}...</p>"
|
||||
value={bodyHtml}
|
||||
onChange={(e) => setBodyHtml(e.target.value)}
|
||||
rows={12}
|
||||
|
||||
@@ -476,8 +476,8 @@ function SummaryTab({ summary, workers, loading, dateRange, setDateRange, onRefr
|
||||
<div className="rounded-2xl border border-[var(--admin-border)] bg-white p-4">
|
||||
<div className="flex flex-wrap gap-4 items-end">
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] font-medium">From</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-1-from" className="text-xs text-[var(--admin-text-muted)] font-medium">From</label>
|
||||
<input id="fld-1-from" aria-label="Date"
|
||||
type="date"
|
||||
value={dateRange.start}
|
||||
onChange={(e) => setDateRange((prev) => ({ ...prev, start: e.target.value }))}
|
||||
@@ -485,8 +485,8 @@ function SummaryTab({ summary, workers, loading, dateRange, setDateRange, onRefr
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] font-medium">To</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-2-to" className="text-xs text-[var(--admin-text-muted)] font-medium">To</label>
|
||||
<input id="fld-2-to" aria-label="Date"
|
||||
type="date"
|
||||
value={dateRange.end}
|
||||
onChange={(e) => setDateRange((prev) => ({ ...prev, end: e.target.value }))}
|
||||
@@ -711,8 +711,8 @@ function LogsTab({ logs, workers, tasks, dateRange, setDateRange, selectedWorker
|
||||
<div className="rounded-2xl border border-[var(--admin-border)] bg-white p-4">
|
||||
<div className="flex flex-wrap gap-4 items-end">
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] font-medium">From</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-3-from-2" className="text-xs text-[var(--admin-text-muted)] font-medium">From</label>
|
||||
<input id="fld-3-from-2" aria-label="Date"
|
||||
type="date"
|
||||
value={dateRange.start}
|
||||
onChange={(e) => setDateRange((prev) => ({ ...prev, start: e.target.value }))}
|
||||
@@ -720,8 +720,8 @@ function LogsTab({ logs, workers, tasks, dateRange, setDateRange, selectedWorker
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] font-medium">To</label>
|
||||
<input aria-label="Date"
|
||||
<label htmlFor="fld-4-to-2" className="text-xs text-[var(--admin-text-muted)] font-medium">To</label>
|
||||
<input id="fld-4-to-2" aria-label="Date"
|
||||
type="date"
|
||||
value={dateRange.end}
|
||||
onChange={(e) => setDateRange((prev) => ({ ...prev, end: e.target.value }))}
|
||||
@@ -729,8 +729,8 @@ function LogsTab({ logs, workers, tasks, dateRange, setDateRange, selectedWorker
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] font-medium">Worker</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-5-worker" className="text-xs text-[var(--admin-text-muted)] font-medium">Worker</label>
|
||||
<select id="fld-5-worker" aria-label="Select"
|
||||
value={selectedWorker}
|
||||
onChange={(e) => setSelectedWorker(e.target.value)}
|
||||
className="px-3 py-2 rounded-lg border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] text-sm focus:outline-none focus:border-[var(--admin-accent)] min-w-[160px]"
|
||||
@@ -742,8 +742,8 @@ function LogsTab({ logs, workers, tasks, dateRange, setDateRange, selectedWorker
|
||||
</select>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-xs text-[var(--admin-text-muted)] font-medium">Task</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-6-task" className="text-xs text-[var(--admin-text-muted)] font-medium">Task</label>
|
||||
<select id="fld-6-task" aria-label="Select"
|
||||
value={selectedTask}
|
||||
onChange={(e) => setSelectedTask(e.target.value)}
|
||||
className="px-3 py-2 rounded-lg border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] text-sm focus:outline-none focus:border-[var(--admin-accent)] min-w-[160px]"
|
||||
@@ -858,20 +858,20 @@ function WorkerModal({ worker, brandId, onClose, onSave }: {
|
||||
<GlassModal title={isEdit ? "Edit Worker" : "Add Worker"} onClose={onClose}>
|
||||
<form onSubmit={handleSubmit} className="p-6 space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Name *</label>
|
||||
<input aria-label="Input" value={name} onChange={(e) => setName(e.target.value)} required className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]" />
|
||||
<label htmlFor="fld-7-name" className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Name *</label>
|
||||
<input id="fld-7-name" aria-label="Input" value={name} onChange={(e) => setName(e.target.value)} required className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Role</label>
|
||||
<select aria-label="Select" value={role} onChange={(e) => setRole(e.target.value)} className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]">
|
||||
<label htmlFor="fld-8-role" className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Role</label>
|
||||
<select id="fld-8-role" aria-label="Select" value={role} onChange={(e) => setRole(e.target.value)} className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]">
|
||||
<option value="worker">Worker</option>
|
||||
<option value="supervisor">Supervisor</option>
|
||||
<option value="admin">Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Language</label>
|
||||
<select aria-label="Select" value={lang} onChange={(e) => setLang(e.target.value)} className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]">
|
||||
<label htmlFor="fld-9-language" className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Language</label>
|
||||
<select id="fld-9-language" aria-label="Select" value={lang} onChange={(e) => setLang(e.target.value)} className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]">
|
||||
<option value="en">English</option>
|
||||
<option value="es">Español</option>
|
||||
</select>
|
||||
@@ -943,16 +943,16 @@ function TaskModal({ task, brandId, onClose, onSave }: {
|
||||
<GlassModal title={isEdit ? "Edit Task" : "Add Task"} onClose={onClose}>
|
||||
<form onSubmit={handleSubmit} className="p-6 space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Task Name *</label>
|
||||
<input aria-label="., Harvesting" value={name} onChange={(e) => setName(e.target.value)} required placeholder="e.g., Harvesting" className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]" />
|
||||
<label htmlFor="fld-10-task-name" className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Task Name *</label>
|
||||
<input id="fld-10-task-name" aria-label="., Harvesting" value={name} onChange={(e) => setName(e.target.value)} required placeholder="e.g., Harvesting" className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Name in Spanish</label>
|
||||
<input aria-label="., Cosecha" value={nameEs} onChange={(e) => setNameEs(e.target.value)} placeholder="e.g., Cosecha" className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]" />
|
||||
<label htmlFor="fld-11-name-in-spanish" className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Name in Spanish</label>
|
||||
<input id="fld-11-name-in-spanish" aria-label="., Cosecha" value={nameEs} onChange={(e) => setNameEs(e.target.value)} placeholder="e.g., Cosecha" className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Unit</label>
|
||||
<select aria-label="Select" value={unit} onChange={(e) => setUnit(e.target.value)} className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]">
|
||||
<label htmlFor="fld-12-unit" className="block text-sm font-medium text-[var(--admin-text-secondary)] mb-1">Unit</label>
|
||||
<select id="fld-12-unit" aria-label="Select" value={unit} onChange={(e) => setUnit(e.target.value)} className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--admin-accent)]">
|
||||
<option value="hours">Hours</option>
|
||||
<option value="pieces">Pieces</option>
|
||||
<option value="units">Units</option>
|
||||
|
||||
@@ -528,8 +528,8 @@ export default function TimeTrackingSettingsClient({ brandId }: TimeTrackingSett
|
||||
<h3 className="text-sm font-semibold text-[var(--admin-text-primary)]">Pay Period & Overtime</h3>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-2">Work week starts on</label>
|
||||
<select aria-label="Select" value={payPeriodStartDay} onChange={e => setPayPeriodStartDay(Number(e.target.value))}
|
||||
<label htmlFor="fld-1-work-week-starts-on" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-2">Work week starts on</label>
|
||||
<select id="fld-1-work-week-starts-on" aria-label="Select" value={payPeriodStartDay} onChange={e => setPayPeriodStartDay(Number(e.target.value))}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors">
|
||||
{DAYS.map((d, i) => <option key={d} value={i}>{d}</option>)}
|
||||
</select>
|
||||
@@ -685,23 +685,23 @@ export default function TimeTrackingSettingsClient({ brandId }: TimeTrackingSett
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Name *</label>
|
||||
<input aria-label="Worker Name" value={workerName} onChange={e => setWorkerName(e.target.value)}
|
||||
<label htmlFor="fld-2-name" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Name *</label>
|
||||
<input id="fld-2-name" aria-label="Worker Name" value={workerName} onChange={e => setWorkerName(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] placeholder:text-[var(--admin-text-muted)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors"
|
||||
placeholder="Worker name" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Role</label>
|
||||
<select aria-label="Select" value={workerRole} onChange={e => setWorkerRole(e.target.value)}
|
||||
<label htmlFor="fld-3-role" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Role</label>
|
||||
<select id="fld-3-role" aria-label="Select" value={workerRole} onChange={e => setWorkerRole(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors">
|
||||
<option value="worker">Worker</option>
|
||||
<option value="time_admin">Time Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Lang</label>
|
||||
<select aria-label="Select" value={workerLang} onChange={e => setWorkerLang(e.target.value)}
|
||||
<label htmlFor="fld-4-lang" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Lang</label>
|
||||
<select id="fld-4-lang" aria-label="Select" value={workerLang} onChange={e => setWorkerLang(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors">
|
||||
<option value="en">English</option>
|
||||
<option value="es">Español</option>
|
||||
@@ -744,21 +744,21 @@ export default function TimeTrackingSettingsClient({ brandId }: TimeTrackingSett
|
||||
<div className="p-6 space-y-4">
|
||||
{taskError && <div className="bg-red-50 border border-red-200 rounded-xl py-3 px-4 text-red-700 text-sm">{taskError}</div>}
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Name (EN) *</label>
|
||||
<input aria-label=". Harvesting" value={taskName} onChange={e => setTaskName(e.target.value)}
|
||||
<label htmlFor="fld-5-name-en" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Name (EN) *</label>
|
||||
<input id="fld-5-name-en" aria-label=". Harvesting" value={taskName} onChange={e => setTaskName(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] placeholder:text-[var(--admin-text-muted)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors"
|
||||
placeholder="e.g. Harvesting" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Name (ES)</label>
|
||||
<input aria-label=". Cosecha" value={taskNameEs} onChange={e => setTaskNameEs(e.target.value)}
|
||||
<label htmlFor="fld-6-name-es" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Name (ES)</label>
|
||||
<input id="fld-6-name-es" aria-label=". Cosecha" value={taskNameEs} onChange={e => setTaskNameEs(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] placeholder:text-[var(--admin-text-muted)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors"
|
||||
placeholder="e.g. Cosecha" />
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Unit</label>
|
||||
<select aria-label="Select" value={taskUnit} onChange={e => setTaskUnit(e.target.value)}
|
||||
<label htmlFor="fld-7-unit" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Unit</label>
|
||||
<select id="fld-7-unit" aria-label="Select" value={taskUnit} onChange={e => setTaskUnit(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors">
|
||||
<option value="hours">Hours</option>
|
||||
<option value="pieces">Pieces</option>
|
||||
@@ -766,8 +766,8 @@ export default function TimeTrackingSettingsClient({ brandId }: TimeTrackingSett
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Sort Order</label>
|
||||
<input aria-label="Number" type="number" value={taskSortOrder} onChange={e => setTaskSortOrder(parseInt(e.target.value) || 0)}
|
||||
<label htmlFor="fld-8-sort-order" className="block text-xs font-semibold uppercase tracking-widest text-[var(--admin-text-muted)] mb-1.5">Sort Order</label>
|
||||
<input id="fld-8-sort-order" aria-label="Number" type="number" value={taskSortOrder} onChange={e => setTaskSortOrder(parseInt(e.target.value) || 0)}
|
||||
className="w-full px-4 py-3 rounded-xl border border-[var(--admin-border)] bg-white text-[var(--admin-text-primary)] focus:outline-none focus:border-[var(--admin-accent)] transition-colors" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -539,8 +539,8 @@ export default function UsersPage({ initialUsers, brands, currentUser, onUserCre
|
||||
{/* Email (create only) */}
|
||||
{editing.isNew && (
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-stone-700">Email</label>
|
||||
<input aria-label="User@example.com"
|
||||
<label htmlFor="fld-1-email" className="block text-sm font-medium text-stone-700">Email</label>
|
||||
<input id="fld-1-email" aria-label="User@example.com"
|
||||
type="email"
|
||||
value={editing.email ?? ""}
|
||||
onChange={(e) => setEditing((p) => ({ ...p, email: e.target.value }))}
|
||||
@@ -622,8 +622,8 @@ export default function UsersPage({ initialUsers, brands, currentUser, onUserCre
|
||||
{/* Brand */}
|
||||
{showBrandSelect && (
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-stone-700">Brand</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-2-brand" className="block text-sm font-medium text-stone-700">Brand</label>
|
||||
<select id="fld-2-brand" aria-label="Select"
|
||||
value={editing.brand_id ?? ""}
|
||||
onChange={(e) => setBrand(e.target.value || null)}
|
||||
className="mt-1 w-full rounded-lg border border-stone-200 px-3 py-2.5 text-sm text-stone-900 focus:border-emerald-500 focus:outline-none focus:ring-1 focus:ring-emerald-500"
|
||||
|
||||
@@ -101,8 +101,8 @@ export default function WaterUserEditForm({ waterUser, backHref = "/admin/water-
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Name</label>
|
||||
<input aria-label="Text"
|
||||
<label htmlFor="fld-1-name" className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Name</label>
|
||||
<input id="fld-1-name" aria-label="Text"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
@@ -111,8 +111,8 @@ export default function WaterUserEditForm({ waterUser, backHref = "/admin/water-
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Role</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-2-role" className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Role</label>
|
||||
<select id="fld-2-role" aria-label="Select"
|
||||
value={role}
|
||||
onChange={(e) => setRole(e.target.value as "irrigator" | "water_admin")}
|
||||
className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2 text-sm"
|
||||
@@ -127,8 +127,8 @@ export default function WaterUserEditForm({ waterUser, backHref = "/admin/water-
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Language</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-3-language" className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Language</label>
|
||||
<select id="fld-3-language" aria-label="Select"
|
||||
value={lang}
|
||||
onChange={(e) => setLang(e.target.value)}
|
||||
className="w-full rounded-lg border border-[var(--admin-border)] px-3 py-2 text-sm"
|
||||
@@ -141,8 +141,8 @@ export default function WaterUserEditForm({ waterUser, backHref = "/admin/water-
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Status</label>
|
||||
<select aria-label="Select"
|
||||
<label htmlFor="fld-4-status" className="block text-sm font-medium text-[var(--admin-text-muted)] mb-1">Status</label>
|
||||
<select id="fld-4-status" aria-label="Select"
|
||||
value={active ? "1" : "0"}
|
||||
onChange={(e) => setActive(e.target.value === "1")}
|
||||
className="rounded-lg border border-[var(--admin-border)] px-3 py-2 text-sm"
|
||||
|
||||
Reference in New Issue
Block a user