Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/components/absences/modals/AdminTeacherFields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
FormLabel,
Text,
} from '@chakra-ui/react';
import { useId } from 'react';
import { SearchDropdown } from './SearchDropdown';

interface AdminTeacherFieldsProps {
Expand All @@ -28,14 +29,21 @@ export const AdminTeacherFields: React.FC<AdminTeacherFieldsProps> = ({
setFormData,
setErrors,
}) => {
const id = useId();

return (
<>
<FormControl isRequired isInvalid={!!errors.absentTeacherId}>
<FormLabel htmlFor="absentTeacher" sx={{ display: 'flex' }}>
<FormLabel
id={'absentTeacherLabel' + id}
as="p"
sx={{ display: 'flex' }}
>
<Text textStyle="h4">Teacher Absent</Text>
</FormLabel>
<SearchDropdown
id="absentTeacher"
ariaLabelledBy={'absentTeacherLabel' + id}
excludedId={formData.substituteTeacherId}
defaultValueId={Number(formData.absentTeacherId)}
onChange={(value) => {
Expand All @@ -55,11 +63,16 @@ export const AdminTeacherFields: React.FC<AdminTeacherFieldsProps> = ({
</FormControl>

<FormControl>
<FormLabel htmlFor="substituteTeacher" sx={{ display: 'flex' }}>
<FormLabel
id={'substituteTeacherLabel' + id}
as="p"
sx={{ display: 'flex' }}
>
<Text textStyle="h4">Substitute Teacher</Text>
</FormLabel>
<SearchDropdown
id="substituteTeacher"
ariaLabelledBy={'substituteTeacherLabel' + id}
excludedId={formData.absentTeacherId}
defaultValueId={
formData.substituteTeacherId
Expand Down
7 changes: 5 additions & 2 deletions src/components/absences/modals/DateOfAbsence.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
PopoverTrigger,
Text,
} from '@chakra-ui/react';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useState, useId } from 'react';
import MiniCalendar from '../../calendar/MiniCalendar';

interface DateOfAbsenceProps {
Expand Down Expand Up @@ -66,9 +66,11 @@ export const DateOfAbsence: React.FC<DateOfAbsenceProps> = ({
[onDateSelect]
);

const id = useId();

return (
<FormControl isRequired isInvalid={!!error}>
<FormLabel sx={{ display: 'flex' }}>
<FormLabel as="p" id={'dateOfAbsenceLabel' + id} sx={{ display: 'flex' }}>
<Text textStyle="h4">{label}</Text>
</FormLabel>
<Popover
Expand All @@ -80,6 +82,7 @@ export const DateOfAbsence: React.FC<DateOfAbsenceProps> = ({
<PopoverTrigger>
<Box>
<Input
aria-labelledby={'dateOfAbsenceLabel' + id}
value={inputValue}
onChange={handleInputChange}
placeholder="YYYY-MM-DD"
Expand Down
3 changes: 3 additions & 0 deletions src/components/absences/modals/InputDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import { useCustomToast } from '../../CustomToast';
export type Option = { name: string; id: number };

interface InputDropdownProps {
ariaLabelledBy: string;
label: string;
type: 'location' | 'subject';
onChange: (value: Option | null) => void;
defaultValueId?: number;
}

export const InputDropdown: React.FC<InputDropdownProps> = ({
ariaLabelledBy,
label,
type,
onChange,
Expand Down Expand Up @@ -120,6 +122,7 @@ export const InputDropdown: React.FC<InputDropdownProps> = ({
value={selectedOption ? selectedOption.name : ''}
readOnly
_focusVisible={{ outline: 'none' }}
aria-labelledby={ariaLabelledBy}
/>
<InputRightElement pointerEvents="none">
{isOpen ? <IoChevronUp /> : <IoChevronDown />}
Expand Down
3 changes: 3 additions & 0 deletions src/components/absences/modals/SearchDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ export type Option = { name: string; id: number; profilePicture: string };

interface SearchDropdownProps {
id: string;
ariaLabelledBy: string;
excludedId?: string;
defaultValueId?: number;
onChange: (value: Option | null) => void;
}

export const SearchDropdown: React.FC<SearchDropdownProps> = ({
id,
ariaLabelledBy,
excludedId,
defaultValueId,
onChange,
Expand Down Expand Up @@ -174,6 +176,7 @@ export const SearchDropdown: React.FC<SearchDropdownProps> = ({
id={id}
name={id}
ref={inputRef}
aria-labelledby={ariaLabelledBy}
value={searchQuery}
onChange={isSelected ? undefined : handleSearchChange}
onClick={() => {
Expand Down
21 changes: 15 additions & 6 deletions src/components/absences/modals/declare/DeclareAbsenceForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Absence, Prisma } from '@prisma/client';
import { formatFullDate } from '@utils/dates';
import { submitAbsence } from '@utils/submitAbsence';
import { validateAbsenceForm } from '@utils/validateAbsenceForm';
import { useState } from 'react';
import { useId, useState } from 'react';
import { useCustomToast } from '../../../CustomToast';
import { FileUpload } from '../../FileUpload';
import { AdminTeacherFields } from '../AdminTeacherFields';
Expand Down Expand Up @@ -317,6 +317,8 @@ const DeclareAbsenceForm: React.FC<DeclareAbsenceFormProps> = ({
const isUrgent =
(selectedDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24) <= 7;

const id = useId();

return (
<Box
as="form"
Expand All @@ -337,10 +339,11 @@ const DeclareAbsenceForm: React.FC<DeclareAbsenceFormProps> = ({
)}

<FormControl isRequired isInvalid={!!errors.subjectId}>
<FormLabel sx={{ display: 'flex' }}>
<FormLabel id={'subjectLabel' + id} as="p" sx={{ display: 'flex' }}>
<Text textStyle="h4">Subject</Text>
</FormLabel>
<InputDropdown
ariaLabelledBy={'subjectLabel' + id}
label="subject"
type="subject"
onChange={(value) => {
Expand All @@ -360,10 +363,11 @@ const DeclareAbsenceForm: React.FC<DeclareAbsenceFormProps> = ({
</FormControl>

<FormControl isRequired isInvalid={!!errors.locationId}>
<FormLabel sx={{ display: 'flex' }}>
<FormLabel id={'locationLabel' + id} as="p" sx={{ display: 'flex' }}>
<Text textStyle="h4">Location</Text>
</FormLabel>
<InputDropdown
ariaLabelledBy={'locationLabel' + id}
label="location"
type="location"
onChange={(value) => {
Expand All @@ -381,29 +385,33 @@ const DeclareAbsenceForm: React.FC<DeclareAbsenceFormProps> = ({
/>
<FormErrorMessage>{errors.locationId}</FormErrorMessage>
</FormControl>

<FormControl>
<FormLabel htmlFor="roomNumber" sx={{ display: 'flex' }}>
<FormLabel id={'roomNumberLabel' + id} sx={{ display: 'flex' }}>
<Text textStyle="h4">Room Number</Text>
</FormLabel>
<Input
aria-labelledby={'roomNumberLabel' + id}
id="roomNumber"
name="roomNumber"
placeholder="e.g. 2131"
value={formData.roomNumber}
onChange={handleChange}
/>
</FormControl>

<DateOfAbsence
dateValue={dateValue}
onDateSelect={handleDateSelect}
error={errors.lessonDate}
/>

<FormControl isRequired isInvalid={!!errors.reasonOfAbsence}>
<FormLabel htmlFor="reasonOfAbsence" sx={{ display: 'flex' }}>
<FormLabel id={'reasonOfAbsenceLabel' + id} sx={{ display: 'flex' }}>
<Text textStyle="h4">Reason of Absence</Text>
</FormLabel>
<Textarea
aria-labelledby={'reasonOfAbsenceLabel' + id}
id="reasonOfAbsence"
name="reasonOfAbsence"
placeholder="Only visible to admin"
Expand All @@ -422,10 +430,11 @@ const DeclareAbsenceForm: React.FC<DeclareAbsenceFormProps> = ({
</FormControl>

<FormControl>
<FormLabel htmlFor="notes" sx={{ display: 'flex' }}>
<FormLabel id={'notesLabel' + id} sx={{ display: 'flex' }}>
<Text textStyle="h4">Notes</Text>
</FormLabel>
<Textarea
aria-labelledby={'notesLabel' + id}
id="notes"
name="notes"
placeholder="Visible to everyone"
Expand Down
19 changes: 13 additions & 6 deletions src/components/absences/modals/edit/EditAbsenceForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { formatFullDate } from '@utils/dates';
import { submitAbsence } from '@utils/submitAbsence';
import { EventDetails } from '@utils/types';
import { validateAbsenceForm } from '@utils/validateAbsenceForm';
import { useState } from 'react';
import { useState, useId } from 'react';
import { IoMailOutline } from 'react-icons/io5';
import { useCustomToast } from '../../../CustomToast';
import { FileUpload } from '../../FileUpload';
Expand Down Expand Up @@ -282,6 +282,8 @@ const EditAbsenceForm: React.FC<EditAbsenceFormProps> = ({
}
};

const id = useId();

return (
<Box
as="form"
Expand All @@ -300,10 +302,11 @@ const EditAbsenceForm: React.FC<EditAbsenceFormProps> = ({
)}

<FormControl isRequired isInvalid={!!errors.subjectId}>
<FormLabel sx={{ display: 'flex' }}>
<FormLabel id={'subjectLabel' + id} as="p" sx={{ display: 'flex' }}>
<Text textStyle="h4">Subject</Text>
</FormLabel>
<InputDropdown
ariaLabelledBy={'subjectLabel' + id}
label="subject"
type="subject"
onChange={(value) => {
Expand All @@ -324,10 +327,11 @@ const EditAbsenceForm: React.FC<EditAbsenceFormProps> = ({
</FormControl>

<FormControl isRequired isInvalid={!!errors.locationId}>
<FormLabel sx={{ display: 'flex' }}>
<FormLabel id={'locationLabel' + id} as="p" sx={{ display: 'flex' }}>
<Text textStyle="h4">Location</Text>
</FormLabel>
<InputDropdown
ariaLabelledBy={'locationLabel' + id}
label="location"
type="location"
onChange={(value) => {
Expand All @@ -348,10 +352,11 @@ const EditAbsenceForm: React.FC<EditAbsenceFormProps> = ({
</FormControl>

<FormControl>
<FormLabel htmlFor="roomNumber" sx={{ display: 'flex' }}>
<FormLabel id={'roomNumberLabel' + id} sx={{ display: 'flex' }}>
<Text textStyle="h4">Room Number</Text>
</FormLabel>
<Input
aria-labelledby={'roomNumberLabel' + id}
id="roomNumber"
name="roomNumber"
placeholder="e.g. 2131"
Expand All @@ -367,10 +372,11 @@ const EditAbsenceForm: React.FC<EditAbsenceFormProps> = ({
/>

<FormControl isRequired isInvalid={!!errors.reasonOfAbsence}>
<FormLabel htmlFor="reasonOfAbsence" sx={{ display: 'flex' }}>
<FormLabel id={'reasonOfAbsenceLabel' + id} sx={{ display: 'flex' }}>
<Text textStyle="h4">Reason of Absence</Text>
</FormLabel>
<Textarea
aria-labelledby={'reasonOfAbsenceLabel' + id}
id="reasonOfAbsence"
name="reasonOfAbsence"
placeholder="Only visible to admin"
Expand All @@ -393,10 +399,11 @@ const EditAbsenceForm: React.FC<EditAbsenceFormProps> = ({
</FormControl>

<FormControl>
<FormLabel htmlFor="notes" sx={{ display: 'flex' }}>
<FormLabel id={'notesLabel' + id} sx={{ display: 'flex' }}>
<Text textStyle="h4">Notes</Text>
</FormLabel>
<Textarea
aria-labelledby={'notesLabel' + id}
id="notes"
name="notes"
placeholder="Visible to everyone"
Expand Down