Skip to content

Commit

Permalink
Feature/booking and tickets accessibility (#551)
Browse files Browse the repository at this point in the history
* feat(cta-button): add accessibility

* feat(icon-button): add iconPadding prop

* feat(tickets): add accessibility

* feat(tickets-faqs): add accessibility

* feat(services): add accessibility

* feat(create-ticket): add accessibility

* feat(news-item): add accessibility

* feat(ticket-faq): add accessibility

* feat(creat-ticket): add accessibility

* feat(tickets-list): add accessibility

* fix(tickets-list): accessibility

* fix(tickets-faq): accessibility

* feat(ticket-status-info): accessibility

* feat(messaging-view): accessibility

* fix(messaging-view): accessibility

* fix(ticket-screen): accessibility

* feat(chat-message): accessibility

* feat(ticket-status-info): ios accessibility

* feat(ticket-screen): ios accessibility

* feat(bookings-screen): accessibility

* feat(booking-screen): accessibility

* feat(booking-list-item): accessibility

* fix(booking-list-item): accessibility

* feat(booking-date-time): accessibility

* fix(booking-screen): accessibility

* fix(ticket-screen): accessibility

* fix(ticket-screen): accessibility

* fix(ticket-faq-screen): accessibility

* fix(create-ticket-screen): accessibility

* fix(chat-message): accessibility

* fix(messaging-view): accessibility

* fix(ticket-status-info): accessibility

* fix(booking-slot-screen): accessibility

* fix(booking-slot-screen): accessibility

* fix(booking-slot-screen): week-filter accessibility

* feat(booking-screen): confirm booking accessibility

* feat(modal-content): accessibility

* feat(booking-slot-modal): accessibility

* fix(booking): accessibility

* fix(booking): accessibility

* fix(booking): accessibility

* fix(booking-slot-modal): accessibility

* fix(booking-seats-cta): accessibility

* fix(booking): accessibility

* fix(booking): accessibility

* feat(labels): accessibility

* fix(booking-seat-selection-screen): accessibility

* fix(attachment-chip): accessibility

* feat(empty-state): accessibility

* feat(cta-button): add accessibility

* feat(icon-button): add iconPadding prop

* feat(tickets): add accessibility

* feat(tickets-faqs): add accessibility

* feat(services): add accessibility

* feat(create-ticket): add accessibility

* feat(news-item): add accessibility

* feat(ticket-faq): add accessibility

* feat(creat-ticket): add accessibility

* feat(tickets-list): add accessibility

* fix(tickets-list): accessibility

* fix(tickets-faq): accessibility

* feat(ticket-status-info): accessibility

* feat(messaging-view): accessibility

* fix(messaging-view): accessibility

* fix(ticket-screen): accessibility

* feat(chat-message): accessibility

* feat(ticket-status-info): ios accessibility

* feat(ticket-screen): ios accessibility

* feat(bookings-screen): accessibility

* feat(booking-screen): accessibility

* feat(booking-list-item): accessibility

* fix(booking-list-item): accessibility

* feat(booking-date-time): accessibility

* fix(booking-screen): accessibility

* fix(ticket-screen): accessibility

* fix(ticket-screen): accessibility

* fix(ticket-faq-screen): accessibility

* fix(create-ticket-screen): accessibility

* fix(chat-message): accessibility

* fix(messaging-view): accessibility

* fix(ticket-status-info): accessibility

* fix(booking-slot-screen): accessibility

* fix(booking-slot-screen): accessibility

* fix(booking-slot-screen): week-filter accessibility

* feat(booking-screen): confirm booking accessibility

* feat(modal-content): accessibility

* feat(booking-slot-modal): accessibility

* fix(booking): accessibility

* fix(booking): accessibility

* fix(booking): accessibility

* fix(booking-slot-modal): accessibility

* fix(booking-seats-cta): accessibility

* fix(booking): accessibility

* fix(booking): accessibility

* feat(labels): accessibility

* fix(booking-seat-selection-screen): accessibility

* fix(attachment-chip): accessibility

* feat(empty-state): accessibility

* fix(booking-hooks): accessibility

* feat: add helpers in utils, used camel case in translation

* feat: add helpers in utils, used camel case in translation

---------

Co-authored-by: alessandropremoli <[email protected]>
Co-authored-by: miky41195 <[email protected]>
Co-authored-by: Emanuele Coricciati <[email protected]>
  • Loading branch information
4 people authored Jan 28, 2025
1 parent a89b8c5 commit 9a8dc16
Show file tree
Hide file tree
Showing 41 changed files with 654 additions and 174 deletions.
37 changes: 32 additions & 5 deletions assets/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"available": "Prenotabile",
"booked": "Prenotato",
"full": "Non prenotabile",
"notAvailable": "Non ancora prenotabile"
"notAvailable": "Non ancora prenotabile",
"notAvailableBooking": "Non prenotabile"
},
"cancelBooking": "Annulla prenotazione",
"cancelBookingText": "Sei sicuro di voler annullare la prenotazione?",
Expand All @@ -28,14 +29,18 @@
"locationType": {
"place": "Luogo",
"virtualPlace": "Link sportello virtuale"
}
},
"nextWeek": "Prossima settimana",
"previousWeek": "Settimana precedente"
},
"bookingSeatScreen": {
"confirm": "Conferma prenotazione",
"confirmSuccess": "Prenotazione confermata",
"deadlineExpired": "Siamo spiacenti,\nè scaduto il termine ultimo per potersi prenotare a questo turno",
"noSeatSelected": "Nessuna",
"noSeatsAvailable": "Siamo spiacenti,\nnon ci sono posti disponibili",
"seatStatus": {
"unavailable": "Non prenotabile",
"available": "Disponibile",
"booked": "Prenotato",
"notAvailable": "Non prenotabile"
Expand Down Expand Up @@ -72,6 +77,8 @@
"yellow": "Giallo"
},
"common": {
"active": "Attivo",
"disabledPreviousValue": "Disattivato perche non sono stati inseriti i precedenti valori",
"actionPotentiallyNotUndoable": "Questa azione potrebbe non essere annullabile",
"activeStatus": {
"false": "Non attiva",
Expand Down Expand Up @@ -191,6 +198,7 @@
"open": "Apri",
"openSettings": "Apri impostazioni",
"openSource": "Open Source",
"openSourceAccessibilityLabel": "Open Source, Tocca per andare al repository GitHub della App",
"openedStatus": {
"false": "Chiuso",
"true": "Aperto"
Expand Down Expand Up @@ -248,7 +256,10 @@
"virtualClassroom_plural": "Virtual classroom",
"visualization": "Visualizzazione",
"year": "anno",
"yesterday": "Ieri"
"yesterday": "Ieri",
"fromTime" : "dalle",
"toTime" : "alle",
"document" : "Allegato"
},
"contactsScreen": {
"cancelRecentSearch": "Rimuovi",
Expand Down Expand Up @@ -374,6 +385,7 @@
"total": "Sono presenti {{ total }} questionari"
},
"createTicketScreen": {
"addFile": "Aggiungi file",
"insert": "Inserimento ticket",
"messageLabel": "Descrivi il tuo problema e, se vuoi, allega un file",
"sendTicket": "Invia ticket",
Expand All @@ -382,6 +394,8 @@
"subtitle": "Inserisci la tua richiesta",
"subtopicDescription": "Seleziona il sottoargomento",
"subtopicDropdownLabel": "Sottoargomento",
"subtopicDropdownLabelAccessibility": "Sottoargomento, apri e scegli tra le opzioni",
"topicDropdownLabelAccessibility": "Argomento, apri e scegli tra le opzioni",
"subtopicDropdownPlaceholder": "Seleziona il sottoargomento",
"title": "Nuovo ticket",
"topicDescription": "Seleziona l'argomento",
Expand Down Expand Up @@ -500,6 +514,7 @@
"title": "Biblioteca"
},
"loginScreen": {
"onboarding" : "Onboarding",
"authnError": "Errore di autenticazione",
"authnErrorDescription": "Le credenziali che hai inserito potrebbero essere errate.",
"cta": "Accedi",
Expand Down Expand Up @@ -529,6 +544,7 @@
"youHaveUnreadMessages": "Hai {{total}} messaggi non letti"
},
"messagingView": {
"activeReplay": "Attivo, (tocca due volte per attivare)",
"pickFile": "Scegli un file",
"pickFileHint": "Dal tuo dispositivo o dal cloud",
"pickPhoto": "Scegli un'immagine",
Expand Down Expand Up @@ -664,7 +680,10 @@
"servicesScreen": {
"subTitleOne": "Servizi informativi",
"subTitleTwo": "Servizi operativi",
"title": "Servizi"
"title": "Servizi",
"newElement": ", hai Un nuovo elemento da visualizzare",
"favoriteActive": "Imposta preferito, Attivo",
"favoriteInactive": "Imposta preferito, Non attivo"
},
"settingsScreen": {
"appVersion": "Versione {{version}}",
Expand Down Expand Up @@ -694,9 +713,11 @@
"headerBackTitle": "Nuovo",
"noResultFound": "Non hai trovato quello che cerchi?",
"title": "FAQ",
"writeTicket": "Scrivi ticket"
"writeTicket": "Scrivi ticket",
"writeTicketMessage": "Scrivi ticket se non hai trovato quello che cerchi"
},
"ticketFaqsScreen": {
"searchButton": "Attiva per cercare le parole chiave inserite tra le faq",
"emptyState": "Nessun risultato trovato",
"findFAQ": "Cerca tra le FAQ",
"findFAQSubtitle": "Prima di inserire un ticket cerca una risposta tra le FAQ.",
Expand All @@ -707,6 +728,10 @@
"writeTicket": "Scrivi ticket"
},
"ticketScreen": {
"incomingMessage": "la tua risposta",
"outgoingMessage": "Risposta da operatore numero",
"yourQuestion": "La tua domanda",
"send" : "Invia",
"headerBackTitle": "Tickets",
"new": "Nuovo ticket",
"pickFileTitle": "Puoi includere un allegato per messaggio",
Expand All @@ -727,6 +752,8 @@
}
},
"ticketsScreen": {
"noOpenTickets": "Non ci sono ticket aperti",
"noClosedTickets": "Non ci sono ticket chiusi",
"addNew": "Nuovo ticket",
"closed": "Ticket chiusi",
"closedEmptyState": "Non ci sono ticket chiusi",
Expand Down
9 changes: 8 additions & 1 deletion lib/ui/components/CtaButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,14 @@ export const CtaButton = ({
containerStyle,
]}
>
{hint && <Text style={styles.hint}>{hint}</Text>}
{hint && (
<View
importantForAccessibility="no-hide-descendants"
accessibilityElementsHidden={true}
>
<Text style={styles.hint}>{hint}</Text>
</View>
)}
<TouchableHighlight
accessibilityRole="button"
underlayColor={underlayColor}
Expand Down
3 changes: 3 additions & 0 deletions lib/ui/components/EmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export const EmptyState = ({

return (
<Col
accessibilityRole="text"
accessible={true}
accessibilityLabel={message}
align="center"
style={{
padding: _spacing[spacing as unknown as keyof Theme['spacing']],
Expand Down
4 changes: 3 additions & 1 deletion lib/ui/components/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ type Props = Omit<FAProps, 'style'> &
adjustSpacing?: 'left' | 'right';
loading?: boolean;
noPadding?: boolean;
iconPadding?: number;
};

export const IconButton = ({
iconStyle,
loading,
adjustSpacing,
iconPadding,
noPadding = false,
...rest
}: Props) => {
Expand Down Expand Up @@ -49,7 +51,7 @@ export const IconButton = ({
transform,
testID,
};
const padding = spacing[3] as number;
const padding = iconPadding || (spacing[3] as number);
return (
<TouchableOpacity
hitSlop={{
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/components/Metric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ export const Metric = ({ title, value, color, ...rest }: CardProps & Props) => {

return (
<View {...rest}>
{title && <Text>{title}</Text>}
{title && <Text accessible={false}>{title}</Text>}
{['string', 'number'].includes(typeof value) ? (
<Text
accessible={false}
style={[
{
color: color ?? palettes.secondary[dark ? 500 : 600],
Expand Down
11 changes: 10 additions & 1 deletion lib/ui/components/ModalContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PropsWithChildren } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, View } from 'react-native';

import { faTimes } from '@fortawesome/free-solid-svg-icons';
Expand All @@ -19,6 +20,8 @@ export const ModalContent = ({
title,
}: PropsWithChildren<Props>) => {
const styles = useStylesheet(createStyles);
const { t } = useTranslation();

return (
<View style={styles.container}>
<HeaderAccessory
Expand All @@ -28,7 +31,13 @@ export const ModalContent = ({
>
<View style={styles.headerLeft} />
<Text style={styles.modalTitle}>{title}</Text>
<IconButton icon={faTimes} onPress={close} adjustSpacing="left" />
<IconButton
accessibilityLabel={t('common.close')}
accessibilityRole="button"
icon={faTimes}
onPress={close}
adjustSpacing="left"
/>
</HeaderAccessory>
<View>{children}</View>
</View>
Expand Down
8 changes: 7 additions & 1 deletion lib/ui/components/ScreenDateTime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ interface Props {
date?: string;
time?: string;
inListItem?: boolean;
accessibilityLabel?: string;
}

export const ScreenDateTime = ({
accessible,
accessibilityLabel,
date,
time,
inListItem = false,
Expand All @@ -27,7 +29,11 @@ export const ScreenDateTime = ({
}, [colors.prose, dark, inListItem, palettes.gray]);

return (
<Row gap={3} accessible={accessible}>
<Row
accessibilityLabel={accessibilityLabel}
gap={3}
accessible={accessible}
>
<Row gap={2} align="center">
<Icon icon={faCalendar} color={color} size={fontSizes.md} />
<Text style={{ fontSize: fontSizes.md, color }}>{date ?? ''}</Text>
Expand Down
38 changes: 23 additions & 15 deletions lib/ui/components/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useMemo } from 'react';
import { Pressable } from 'react-native';

import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { Icon } from '@lib/ui/components/Icon';
Expand All @@ -22,10 +23,12 @@ interface Props {
label: string;
description?: string;
disabled?: boolean;
accessibilityLabel?: string;
}

export const Select = ({
options,
accessibilityLabel,
onSelectOption,
value,
label,
Expand All @@ -37,21 +40,26 @@ export const Select = ({
}, [options, value]);

return (
<StatefulMenuView
style={{ width: '100%' }}
title={label}
actions={!disabled ? options : []}
onPressAction={({ nativeEvent: { event } }) => {
!disabled && onSelectOption?.(event);
}}
<Pressable
accessibilityRole="button"
accessibilityLabel={accessibilityLabel || label}
>
<ListItem
isAction
disabled={disabled}
title={displayedValue || label}
subtitle={description}
trailingItem={IS_ANDROID ? <Icon icon={faChevronDown} /> : undefined}
/>
</StatefulMenuView>
<StatefulMenuView
style={{ width: '100%' }}
title={label}
actions={!disabled ? options : []}
onPressAction={({ nativeEvent: { event } }) => {
!disabled && onSelectOption?.(event);
}}
>
<ListItem
isAction
disabled={disabled}
title={displayedValue || label}
subtitle={description}
trailingItem={IS_ANDROID ? <Icon icon={faChevronDown} /> : undefined}
/>
</StatefulMenuView>
</Pressable>
);
};
5 changes: 3 additions & 2 deletions src/core/components/EventDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ScreenTitle } from '@lib/ui/components/ScreenTitle';
import { Text } from '@lib/ui/components/Text';
import { useTheme } from '@lib/ui/hooks/useTheme';

import { formatTime } from '../../utils/dates';
import { dateFormatter } from '../../utils/dates';

type Props = ViewProps & {
title?: string;
Expand All @@ -23,6 +23,7 @@ export const EventDetails = ({
...rest
}: Props) => {
const { spacing, fontSizes } = useTheme();
const formatHHmm = dateFormatter('HH:mm');
return (
<View style={{ padding: spacing[5] }} {...rest}>
<ScreenTitle style={{ marginBottom: spacing[2] }} title={title} />
Expand All @@ -33,7 +34,7 @@ export const EventDetails = ({
(typeof time === 'string' ? (
<Text style={{ fontSize: fontSizes.md }}>
{time}
{endTime && ` - ${formatTime(endTime)}`}
{endTime && ` - ${formatHHmm(endTime)}`}
</Text>
) : (
time
Expand Down
6 changes: 6 additions & 0 deletions src/core/hooks/useConfirmationDialog.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useTranslation } from 'react-i18next';
import { Alert } from 'react-native';

import { setTimeoutAccessibilityInfoHelper } from '../../utils/setTimeoutAccessibilityInfo';

interface Options {
title?: string;
message?: string;
Expand All @@ -10,6 +12,10 @@ export const useConfirmationDialog = ({ title, message }: Options = {}) => {
const { t } = useTranslation();
return () =>
new Promise<boolean>(resolve => {
setTimeoutAccessibilityInfoHelper(
t('bookingScreen.cancelBookingText'),
500,
);
Alert.alert(
title ?? t('common.areYouSure?'),
message ?? t('common.actionPotentiallyNotUndoable'),
Expand Down
8 changes: 8 additions & 0 deletions src/core/queries/bookingHooks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { useTranslation } from 'react-i18next';

import { BookingsApi } from '@polito/api-client';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';

import { DateTime } from 'luxon';

import { pluckData } from '../../utils/queries';
import { setTimeoutAccessibilityInfoHelper } from '../../utils/setTimeoutAccessibilityInfo';

export const BOOKINGS_QUERY_KEY = ['bookings'];
export const BOOKINGS_TOPICS_QUERY_KEY = ['booking', 'topics'];
Expand Down Expand Up @@ -148,9 +151,14 @@ export const useCreateBooking = () => {
export const useDeleteBooking = (bookingId: number) => {
const bookingClient = useBookingClient();
const client = useQueryClient();
const { t } = useTranslation();

return useMutation(() => bookingClient.deleteBookingRaw({ bookingId }), {
onSuccess() {
setTimeoutAccessibilityInfoHelper(
t('bookingScreen.cancelFeedback'),
1200,
);
return Promise.all([
client.invalidateQueries(BOOKINGS_QUERY_KEY),
client.invalidateQueries(['agenda']),
Expand Down
Loading

0 comments on commit 9a8dc16

Please sign in to comment.