Skip to content

Commit

Permalink
fix: use translations as only labels in multi option fields
Browse files Browse the repository at this point in the history
  • Loading branch information
siddarth2824 committed Jun 17, 2024
1 parent 7048d0b commit 40d39bd
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { Divider, Flex, HStack, IconButton } from '@chakra-ui/react'
import { BiChevronDown } from 'react-icons/bi'
import {
Box,
Button,
Divider,
Flex,
HStack,
IconButton,
Menu,
MenuButton,
MenuItem,
MenuList,
Text,
} from '@chakra-ui/react'

import { Language } from '~shared/types'

import { SingleSelect } from '~components/Dropdown'

import { usePublicFormContext } from '~features/public-form/PublicFormContext'

import { useBgColor } from '../PublicFormWrapper'
Expand All @@ -12,6 +23,18 @@ import { FontDefaultSvgr } from './FontDefaultSvgr'
import { FontLargestSvgr } from './FontLargestSvgr'
import { FontLargeSvgr } from './FontLargeSvgr'

type LanguageListType = {
language: Language
title: string
}

const LANGUAGES: LanguageListType[] = [
{ language: Language.ENGLISH, title: 'English' },
{ language: Language.CHINESE, title: '中文' },
{ language: Language.MALAY, title: 'Melayu' },
{ language: Language.TAMIL, title: 'தமிழ்' },
]

export const ZoomControl = ({
setDefaultSize,
setLargeSize,
Expand All @@ -24,13 +47,17 @@ export const ZoomControl = ({
const { form, publicFormLanguage, setPublicFormLanguage } =
usePublicFormContext()

const availableLanguages = form?.supportedLanguages ?? []
const availableLanguages = new Set(form?.supportedLanguages ?? [])

const languagesList = LANGUAGES.filter((language) =>
availableLanguages.has(language.language),
)

// English language is always supported. Hence if form supports multi-lang
// and there is more than one supported language available, show the
// language dropdown.
const shouldShowLanguageDropdown =
form?.hasMultiLang && availableLanguages.length > 1
form?.hasMultiLang && availableLanguages.size > 1

const bgColour = useBgColor({
colorTheme: form?.startPage.colorTheme,
Expand All @@ -42,6 +69,10 @@ export const ZoomControl = ({
}
}

const selectedLanguage = LANGUAGES.find(
(language) => language.language === publicFormLanguage,
)?.title

return (
<Flex
background={bgColour}
Expand All @@ -50,25 +81,42 @@ export const ZoomControl = ({
justifyContent={{ base: 'start', md: 'center' }}
>
<HStack
mt="-2rem"
mt="-32px"
bg="white"
borderRadius="4px"
height="3.25rem"
height="52px"
shadow="md"
py={4}
pl={4}
pr={2}
py="14px"
pl="16px"
pr="16px"
>
{shouldShowLanguageDropdown && (
<SingleSelect
placeholder={publicFormLanguage ?? Language.ENGLISH}
value={publicFormLanguage ?? Language.ENGLISH}
onChange={handleLanguageChange}
name={'select form language'}
items={availableLanguages}
isClearable={false}
colorScheme="primary"
/>
<Box mr="48px">
<Menu variant="clear">
<MenuButton
as={Button}
rightIcon={<BiChevronDown />}
variant="clear"
color="secondary.500"
size="16px"
>
<Text fontSize="16px">{selectedLanguage}</Text>
</MenuButton>
<MenuList>
{languagesList.map((language) => {
return (
<MenuItem
onClick={() => {
handleLanguageChange(language.language)
}}
>
<Text fontSize="16px">{language.title}</Text>
</MenuItem>
)
})}
</MenuList>
</Menu>
</Box>
)}

<IconButton
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/templates/Field/Checkbox/CheckboxField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export const CheckboxField = ({
[disableRequiredValidation, schema],
)

const defaultEnglishCheckboxOptions = schema.fieldOptions

const { register, getValues, control } = useFormContext<CheckboxFieldInputs>()
const { isValid, isSubmitting, errors } = useFormState<CheckboxFieldInputs>({
name: schema._id,
Expand Down Expand Up @@ -113,7 +115,11 @@ export const CheckboxField = ({
name={checkboxInputName}
colorScheme={fieldColorScheme}
key={idx}
value={o}
// Value will always be the default english field option
// so that upon form submission, the selected value submitted
// and collected will always be the english field option regardless
// of the language of the form.
value={defaultEnglishCheckboxOptions[idx]}
aria-label={o}
{...(idx === 0 ? { ref } : {})}
>
Expand Down
24 changes: 21 additions & 3 deletions frontend/src/templates/Field/Dropdown/DropdownField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FormColorTheme } from '~shared/types'

import { createDropdownValidationRules } from '~utils/fieldValidation'
import { SingleSelect } from '~components/Dropdown/SingleSelect'
import { ComboboxItem } from '~components/Dropdown/types'

import { BaseFieldProps, FieldContainer } from '../FieldContainer'
import { DropdownFieldSchema, SingleAnswerFieldInput } from '../types'
Expand All @@ -30,17 +31,34 @@ export const DropdownField = ({

const { control } = useFormContext<SingleAnswerFieldInput>()

const fieldOptions = useMemo(() => {
const fieldOptions: ComboboxItem[] = useMemo(() => {
const defaultEnglishFieldOptions = schema.fieldOptions
const fieldOptionsTranslations = schema?.fieldOptionsTranslations ?? []

const translationIdx = fieldOptionsTranslations.findIndex((translation) => {
return translation.language === selectedLanguage
})

if (translationIdx !== -1) {
return fieldOptionsTranslations[translationIdx].translation
const translatedFieldOptions =
fieldOptionsTranslations[translationIdx].translation

// The label will be the translated option while the value is the
// default English option so that upon form submission, the value recorded
// will be the default english option. The indexes of the translated options
// and the default English options are corresponding with each other.
return translatedFieldOptions.map((translatedFieldOption, index) => {
return {
value: defaultEnglishFieldOptions[index],
label: translatedFieldOption,
}
})
} else {
return schema.fieldOptions
return schema.fieldOptions.map((fieldOption) => {
return {
value: fieldOption,
}
})
}
}, [schema.fieldOptions, schema?.fieldOptionsTranslations, selectedLanguage])

Expand Down
16 changes: 13 additions & 3 deletions frontend/src/templates/Field/Radio/RadioField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const RadioField = ({
[schema._id],
)

const defaultEnglishRadioOptions = schema.fieldOptions

const validationRules = useMemo(
() => createRadioValidationRules(schema, disableRequiredValidation),
[disableRequiredValidation, schema],
Expand Down Expand Up @@ -80,9 +82,13 @@ export const RadioField = ({
if (translationIdx !== -1) {
return fieldOptionsTranslations[translationIdx].translation
} else {
return schema.fieldOptions
return defaultEnglishRadioOptions
}
}, [schema.fieldOptions, schema?.fieldOptionsTranslations, selectedLanguage])
}, [
defaultEnglishRadioOptions,
schema?.fieldOptionsTranslations,
selectedLanguage,
])

return (
<FieldContainer
Expand Down Expand Up @@ -115,7 +121,11 @@ export const RadioField = ({
{fieldOptions.map((option, idx) => (
<Radio
key={idx}
value={option}
// Value will always be the default english field option
// so that upon form submission, the selected value submitted
// and collected will always be the english field option regardless
// of the language of the form.
value={defaultEnglishRadioOptions[idx]}
{...(idx === 0 ? { ref } : {})}
// Required should apply to radio group rather than individual radio.
isRequired={false}
Expand Down
40 changes: 31 additions & 9 deletions frontend/src/templates/Field/Table/ColumnCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
createDropdownValidationRules,
} from '~utils/fieldValidation'
import { SingleSelect } from '~components/Dropdown'
import { ComboboxItem } from '~components/Dropdown/types'
import FormErrorMessage from '~components/FormControl/FormErrorMessage'
import FormLabel from '~components/FormControl/FormLabel'
import Input from '~components/Input'
Expand Down Expand Up @@ -91,15 +92,36 @@ const DropdownColumnCell = ({
[schema, disableRequiredValidation],
)

let fieldOptions = schema.fieldOptions ?? []
const fieldOptionsTranslations = schema?.fieldOptionsTranslations ?? []
const translationsIdx = fieldOptionsTranslations.findIndex(
(translation) => translation.language === selectedLanguage,
)

if (translationsIdx !== -1) {
fieldOptions = fieldOptionsTranslations[translationsIdx].translation
}
const fieldOptions: ComboboxItem[] = useMemo(() => {
const defaultEnglishFieldOptions = schema.fieldOptions ?? []
const fieldOptionsTranslations = schema?.fieldOptionsTranslations ?? []
const translationsIdx = fieldOptionsTranslations.findIndex(
(translation) => translation.language === selectedLanguage,
)

if (translationsIdx !== -1) {
const translatedFieldOptions =
fieldOptionsTranslations[translationsIdx].translation

// The label will be the translated option while the value is the
// default English option so that upon form submission, the value recorded
// and collected will be the default english option. The indexes of the
// translated options and the default English options are corresponding
// with each other.
return translatedFieldOptions.map((translatedFieldOption, index) => {
return {
value: defaultEnglishFieldOptions[index],
label: translatedFieldOption,
}
})
} else {
return defaultEnglishFieldOptions.map((fieldOption) => {
return {
value: fieldOption,
}
})
}
}, [schema.fieldOptions, schema?.fieldOptionsTranslations, selectedLanguage])

return (
<Controller
Expand Down
2 changes: 1 addition & 1 deletion shared/types/form/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export enum Language {
ENGLISH = 'English',
CHINESE = 'Chinese',
MALAY = 'Malay',
Tamil = 'Tamil',
TAMIL = 'Tamil',
}

export enum FormStatus {
Expand Down

0 comments on commit 40d39bd

Please sign in to comment.