Skip to content

Commit 90db46b

Browse files
committed
Add visual indicators to required form fields across the application to
improve UX. Updated Label component to support `required` prop and added indicators to employee, location, ride, and rider forms. MUI components use `required` prop; DatePicker/TimePicker use asterisks in label strings.
1 parent a07bba8 commit 90db46b

8 files changed

Lines changed: 72 additions & 52 deletions

File tree

frontend/src/components/EmployeeModal/EmployeeInfo.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const EmployeeInfo = ({
2727
return (
2828
<div className={styles.inputContainer}>
2929
<div className={styles.col1}>
30-
<Label htmlFor="firstName">First Name</Label>
30+
<Label htmlFor="firstName" required>First Name</Label>
3131
<Input
3232
id="firstName"
3333
type="text"
@@ -41,7 +41,7 @@ const EmployeeInfo = ({
4141
)}
4242
</div>
4343
<div className={styles.col2}>
44-
<Label htmlFor="lastName">Last Name</Label>
44+
<Label htmlFor="lastName" required>Last Name</Label>
4545
<Input
4646
id="lastName"
4747
type="text"
@@ -55,7 +55,7 @@ const EmployeeInfo = ({
5555
)}
5656
</div>
5757
<div className={styles.col1}>
58-
<Label htmlFor="netid">NetID</Label>
58+
<Label htmlFor="netid" required>NetID</Label>
5959
<Input
6060
id="netid"
6161
type="text"
@@ -69,7 +69,7 @@ const EmployeeInfo = ({
6969
)}
7070
</div>
7171
<div className={styles.col2}>
72-
<Label htmlFor="phoneNumber">Phone Number</Label>
72+
<Label htmlFor="phoneNumber" required>Phone Number</Label>
7373
<Input
7474
id="phoneNumber"
7575
type="tel"

frontend/src/components/EmployeeModal/StartDate.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const StartDate = ({ existingDate }: StartDateProps) => {
1414

1515
return (
1616
<div className={cn(styles.col1, styles.workingHours)}>
17-
<Label htmlFor="startDate">Start Date:</Label>
17+
<Label htmlFor="startDate" required>Start Date:</Label>
1818
<Input
1919
id="startDate"
2020
type="date"

frontend/src/components/FormElements/FormElements.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,19 @@ import {
1313
type LabelType = React.DetailedHTMLProps<
1414
React.LabelHTMLAttributes<HTMLLabelElement>,
1515
HTMLLabelElement
16-
>;
16+
> & {
17+
required?: boolean;
18+
};
1719

18-
export const Label = ({ className, children, ...props }: LabelType) => (
19-
<label {...props} className={cn(styles.label, className)}>
20-
{children}
21-
</label>
22-
);
20+
export const Label = ({ className, children, required, ...props }: LabelType) => {
21+
console.log('Label required:', required); // Debug line
22+
return (
23+
<label {...props} className={cn(styles.label, className)}>
24+
{children}
25+
{required && <span className={styles.requiredIndicator}> *</span>}
26+
</label>
27+
);
28+
};
2329

2430
// This should only be used when you don't want a label to visually appear on screen
2531
// Source: https://webaim.org/techniques/css/invisiblecontent/#techniques
@@ -78,7 +84,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
7884
ref={ref}
7985
onClick={disabled ? undefined : onClick} // Disable click handler if disabled
8086
disabled={disabled}
81-
// onClick={onClick}
87+
// onClick={onClick}
8288
>
8389
{children}
8490
</button>

frontend/src/components/FormElements/formelements.module.css

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,25 @@
5353
border: 0.063rem solid #000000;
5454
box-sizing: border-box;
5555
}
56+
5657
.primaryBtn:focus {
5758
box-shadow: 0 0 0 3px #0075db;
5859
}
60+
5961
.secondaryBtn {
6062
background-color: white;
6163
border: 0.063rem solid #000000;
6264
box-sizing: border-box;
6365
}
66+
6467
.secondaryBtn:focus {
6568
box-shadow: 0 0 0 3px #0075db;
6669
}
6770

6871
.srlabel {
6972
border: 0;
70-
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
73+
clip: rect(1px 1px 1px 1px);
74+
/* IE6, IE7 */
7175
clip: rect(1px, 1px, 1px, 1px);
7276
height: 1px;
7377
margin: -1px;
@@ -76,6 +80,7 @@
7680
position: absolute;
7781
width: 1px;
7882
}
83+
7984
::-webkit-input-placeholder {
8085
color: #767676;
8186
opacity: 1;
@@ -97,3 +102,12 @@
97102
color: #767676;
98103
opacity: 1;
99104
}
105+
106+
.requiredIndicator {
107+
color: #eb0023 !important;
108+
/* Force red color */
109+
font-weight: bold;
110+
font-size: 1.1em;
111+
margin-left: 3px;
112+
display: inline-block;
113+
}

frontend/src/components/LocationModal/LocationModal.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ const LocationModal: React.FC<LocationModalProps> = ({
115115
aria-labelledby="location-modal"
116116
>
117117
<div className={styles.inputContainer}>
118-
<Label htmlFor="name">Name</Label>
118+
<Label htmlFor="name" required>Name</Label>
119119
<Input
120120
{...register('name', { required: true })}
121121
type="text"
@@ -128,7 +128,7 @@ const LocationModal: React.FC<LocationModalProps> = ({
128128
<p className={styles.errorMsg}>Please enter a name</p>
129129
)}
130130

131-
<Label htmlFor="address">Address</Label>
131+
<Label htmlFor="address" required>Address</Label>
132132
<Input
133133
{...register('address', { required: true, validate: isAddress })}
134134
type="text"
@@ -141,7 +141,7 @@ const LocationModal: React.FC<LocationModalProps> = ({
141141
<p className={styles.errorMsg}>{errors.address.message}</p>
142142
)}
143143

144-
<Label htmlFor="info">Pickup/Dropoff Info</Label>
144+
<Label htmlFor="info" required>Pickup/Dropoff Info</Label>
145145
<Input
146146
{...register('info', { required: true })}
147147
type="text"
@@ -156,7 +156,7 @@ const LocationModal: React.FC<LocationModalProps> = ({
156156
</p>
157157
)}
158158

159-
<Label htmlFor="tag">Tag</Label>
159+
<Label htmlFor="tag" required>Tag</Label>
160160
<select
161161
{...register('tag', { required: true })}
162162
id="tag"

frontend/src/components/Modal/RiderModalInfo.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ const RiderModalInfo: React.FC<ModalFormProps> = ({
180180
<form onSubmit={handleSubmit(beforeSubmit)} className={styles.form}>
181181
<div className={cn(styles.inputContainer, styles.rideTime)}>
182182
<div className={cn(styles.gridR1, styles.gridCSmall1)}>
183-
<Label className={styles.label} htmlFor="name">
183+
<Label className={styles.label} htmlFor="name" required>
184184
Name:{' '}
185185
</Label>
186186
<Input
@@ -196,7 +196,7 @@ const RiderModalInfo: React.FC<ModalFormProps> = ({
196196
</div>
197197

198198
<div className={cn(styles.gridR1, styles.gridCSmall2)}>
199-
<Label className={styles.label} htmlFor="netid">
199+
<Label className={styles.label} htmlFor="netid" required>
200200
NetID:{' '}
201201
</Label>
202202
<Input
@@ -216,7 +216,7 @@ const RiderModalInfo: React.FC<ModalFormProps> = ({
216216
</div>
217217

218218
<div className={cn(styles.gridR1, styles.gridCSmall3)}>
219-
<Label className={styles.label} htmlFor="phoneNumber">
219+
<Label className={styles.label} htmlFor="phoneNumber" required>
220220
Phone Number:{' '}
221221
</Label>
222222
<Input
@@ -235,7 +235,7 @@ const RiderModalInfo: React.FC<ModalFormProps> = ({
235235
</div>
236236

237237
<div className={cn(styles.gridR2, styles.gridCBig1)}>
238-
<Label className={styles.label} htmlFor="needs">
238+
<Label className={styles.label} htmlFor="needs" required>
239239
Needs:{' '}
240240
</Label>
241241
<div className={styles.needsContainer}>
@@ -300,7 +300,7 @@ const RiderModalInfo: React.FC<ModalFormProps> = ({
300300
</div>
301301

302302
<div className={cn(styles.gridR2, styles.gridCBig2)}>
303-
<Label className={styles.label} htmlFor="address">
303+
<Label className={styles.label} htmlFor="address" required>
304304
Address:{' '}
305305
</Label>
306306
<Input
@@ -322,7 +322,7 @@ const RiderModalInfo: React.FC<ModalFormProps> = ({
322322
<p>Duration</p>
323323
<div className={styles.lastRow}>
324324
<div>
325-
<Label className={styles.label} htmlFor="joinDate">
325+
<Label className={styles.label} htmlFor="joinDate" required>
326326
Join Date:{' '}
327327
</Label>
328328
<Input
@@ -341,7 +341,7 @@ const RiderModalInfo: React.FC<ModalFormProps> = ({
341341
<p></p>
342342
</div>
343343
<div>
344-
<Label className={styles.label} htmlFor="endDate">
344+
<Label className={styles.label} htmlFor="endDate" required>
345345
End Date:{' '}
346346
</Label>
347347
<Input

frontend/src/components/RequestRideModal/RequestRideInfo.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ const RequestRideInfo: React.FC<RequestRideInfoProps> = ({
136136
{((modalType === 'CREATE' && watchRepeating) ||
137137
modalType === 'EDIT_REGULAR' ||
138138
modalType === 'EDIT_SINGLE_RECURRING') && (
139-
<Label htmlFor={'startDate'} className={styles.largeLabel}>
140-
Date
141-
</Label>
142-
)}
139+
<Label htmlFor={'startDate'} className={styles.largeLabel} required>
140+
Date
141+
</Label>
142+
)}
143143
<div className={styles.box}>
144144
{modalType === 'EDIT_ALL_RECURRING' && (
145-
<Label className={styles.boldLabel} htmlFor="startDate">
145+
<Label className={styles.boldLabel} htmlFor="startDate" required>
146146
Starts
147147
</Label>
148148
)}
@@ -194,7 +194,7 @@ const RequestRideInfo: React.FC<RequestRideInfoProps> = ({
194194
{showRepeatingInfo && watchRepeating ? (
195195
<div>
196196
<div className={styles.box}>
197-
<Label className={styles.boldLabel} id="repeats">
197+
<Label className={styles.boldLabel} id="repeats" required>
198198
Repeats
199199
</Label>
200200
<div className={styles.radioBox}>
@@ -278,7 +278,7 @@ const RequestRideInfo: React.FC<RequestRideInfoProps> = ({
278278
</Label>
279279
<div className={styles.box}>
280280
<div className={styles.errorBox}>
281-
<Label className={styles.label} id="pickupLocation">
281+
<Label className={styles.label} id="pickupLocation" required>
282282
Location
283283
</Label>
284284
<select
@@ -307,7 +307,7 @@ const RequestRideInfo: React.FC<RequestRideInfoProps> = ({
307307
)}
308308
</div>
309309
<div className={styles.errorBox}>
310-
<Label className={styles.label} id="pickupTime">
310+
<Label className={styles.label} id="pickupTime" required>
311311
Time
312312
</Label>
313313
<Input
@@ -383,7 +383,7 @@ const RequestRideInfo: React.FC<RequestRideInfoProps> = ({
383383
</Label>
384384
<div className={styles.box}>
385385
<div className={styles.errorBox}>
386-
<Label className={styles.label} id="dropoffLocation">
386+
<Label className={styles.label} id="dropoffLocation" required>
387387
Location
388388
</Label>
389389
<select
@@ -413,7 +413,7 @@ const RequestRideInfo: React.FC<RequestRideInfoProps> = ({
413413
)}
414414
</div>
415415
<div className={styles.errorBox}>
416-
<Label className={styles.label} id="dropoffTime">
416+
<Label className={styles.label} id="dropoffTime" required>
417417
Time
418418
</Label>
419419
<Input

frontend/src/components/RiderComponents/RequestRideDialog.tsx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -430,12 +430,12 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
430430

431431
const handleDateChange =
432432
(field: keyof Pick<FormData, 'date' | 'time' | 'repeatEndDate'>) =>
433-
(newDate: Date | null) => {
434-
setFormData({
435-
...formData,
436-
[field]: newDate,
437-
});
438-
};
433+
(newDate: Date | null) => {
434+
setFormData({
435+
...formData,
436+
[field]: newDate,
437+
});
438+
};
439439

440440
const handleRepeatTypeChange = (
441441
event: React.ChangeEvent<HTMLInputElement>
@@ -493,7 +493,7 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
493493
finalDropoff !== null &&
494494
finalPickup !== null &&
495495
normalizeAddress(finalDropoff?.address) ===
496-
normalizeAddress(finalPickup.address)
496+
normalizeAddress(finalPickup.address)
497497
) {
498498
setInputPickUpError(true);
499499
setInputDropOffError(true);
@@ -588,8 +588,8 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
588588
backgroundColor: formData.pickupLocation
589589
? '#4caf50'
590590
: selectionState === 'pickup'
591-
? '#2196f3'
592-
: '#e0e0e0',
591+
? '#2196f3'
592+
: '#e0e0e0',
593593
color: 'white',
594594
fontSize: '12px',
595595
}}
@@ -603,8 +603,8 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
603603
backgroundColor: formData.dropoffLocation
604604
? '#4caf50'
605605
: selectionState === 'dropoff'
606-
? '#2196f3'
607-
: '#e0e0e0',
606+
? '#2196f3'
607+
: '#e0e0e0',
608608
color: 'white',
609609
fontSize: '12px',
610610
}}
@@ -691,8 +691,8 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
691691
Or select from dropdown:
692692
</h4>
693693

694-
<FormControl fullWidth style={{ marginBottom: '16px' }}>
695-
<InputLabel>Pickup Location</InputLabel>
694+
<FormControl fullWidth required style={{ marginBottom: '16px' }}>
695+
<InputLabel required>Pickup Location</InputLabel>
696696
<Select<string>
697697
value={formData.pickupLocation?.id || ''}
698698
onChange={(event) => {
@@ -744,8 +744,8 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
744744
</div>
745745
)}
746746

747-
<FormControl fullWidth>
748-
<InputLabel>Drop-off Location</InputLabel>
747+
<FormControl fullWidth required>
748+
<InputLabel required>Drop-off Location</InputLabel>
749749
<Select<string>
750750
value={formData.dropoffLocation?.id || ''}
751751
disabled={!formData.pickupLocation} //makes ensuring start and end locations are different simpler
@@ -808,7 +808,7 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
808808
<LocalizationProvider dateAdapter={AdapterDateFns}>
809809
<Stack direction="row" spacing={2}>
810810
<DatePicker
811-
label="Date"
811+
label="Date *"
812812
value={formData.date}
813813
onChange={handleDateChange('date')}
814814
slotProps={{
@@ -818,7 +818,7 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
818818
}}
819819
/>
820820
<TimePicker
821-
label="Time"
821+
label="Time *"
822822
value={formData.time}
823823
onChange={handleDateChange('time')}
824824
slotProps={{
@@ -850,7 +850,7 @@ const RequestRideDialog: React.FC<RequestRideDialogProps> = ({
850850
{formData.repeatType !== 'none' && (
851851
<LocalizationProvider dateAdapter={AdapterDateFns}>
852852
<DatePicker
853-
label="Repeat End Date"
853+
label="Repeat End Date *"
854854
value={formData.repeatEndDate}
855855
onChange={handleDateChange('repeatEndDate')}
856856
slotProps={{

0 commit comments

Comments
 (0)