Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTranslation } from 'react-i18next'
import { Box } from '@chakra-ui/react'

import Button from '~components/Button'
Expand All @@ -8,16 +9,20 @@ import { useCalendarStyles } from './CalendarStyleProvider'
export const CalendarTodayButton = (): JSX.Element => {
const styles = useCalendarStyles()
const { handleTodayClick, colorScheme } = useCalendar()
const { t } = useTranslation('translation', {
keyPrefix: 'features.publicForm.components.fields.calendar',
})

return (
<Box sx={styles.todayLinkContainer}>
<Button
aria-label="Focus on today's date"
aria-label={t('todayAriaLabel')}
colorScheme={colorScheme}
variant="link"
type="button"
onClick={handleTodayClick}
>
Today
{t('today')}
</Button>
</Box>
)
Expand Down
14 changes: 10 additions & 4 deletions frontend/src/components/DatePicker/DatePickerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React, {
useMemo,
useRef,
} from 'react'
import { useTranslation } from 'react-i18next'
import {
CSSObject,
FormControlProps,
Expand Down Expand Up @@ -101,6 +102,9 @@ const useProvideDatePicker = ({
const inputRef = useRef<HTMLInputElement>(null)

const isMobile = useIsMobile()
const { t } = useTranslation('translation', {
keyPrefix: 'features.publicForm.components.fields.datePicker',
})

const disclosureProps = useDisclosure({
onClose: () => {
Expand Down Expand Up @@ -161,16 +165,18 @@ const useProvideDatePicker = ({
)

const calendarButtonAria = useMemo(() => {
let ariaLabel = 'Select from date picker. '
let ariaLabel = t('selectFromDatePicker')
if (internalValue) {
if (isValid(internalValue)) {
ariaLabel += `Selected date is ${internalValue.toLocaleDateString()}.`
ariaLabel += t('selectedDateIs', {
date: internalValue.toLocaleDateString(),
})
} else {
ariaLabel += 'The current selected date is invalid.'
ariaLabel += t('invalidDate')
}
}
return ariaLabel
}, [internalValue])
}, [internalValue, t])

const handleDateChange = useCallback(
(date: Date | null) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { VirtuosoHandle } from 'react-virtuoso'
import {
FormControlOptions,
Expand Down Expand Up @@ -73,9 +74,9 @@ export const MultiSelectProvider = ({
onBlur,
name,
filter = defaultFilter,
nothingFoundLabel = 'No matching results',
nothingFoundLabel,
placeholder: placeholderProp,
clearButtonLabel = 'Clear selection',
clearButtonLabel,
isSearchable = true,
defaultIsOpen,
isInvalid: isInvalidProp,
Expand All @@ -92,6 +93,7 @@ export const MultiSelectProvider = ({
}: MultiSelectProviderProps): JSX.Element => {
const { items, getItemByValue } = useItems({ rawItems })
const [isFocused, setIsFocused] = useState(false)
const { t } = useTranslation()

// Inject for components to manipulate
const inputRef = useRef<HTMLInputElement | null>(null)
Expand Down Expand Up @@ -171,8 +173,19 @@ export const MultiSelectProvider = ({

const dynamicPlaceholder = useMemo(() => {
if (placeholderProp === null || selectedItems.length > 0) return ''
return placeholderProp ?? 'Select options'
}, [placeholderProp, selectedItems.length])
return (
placeholderProp ??
t('features.publicForm.components.fields.dropdown.selectOptions')
)
}, [placeholderProp, selectedItems.length, t])

const nothingFoundLabelTranslated =
nothingFoundLabel ??
t('features.publicForm.components.fields.dropdown.nothingFound')

const clearButtonLabelTranslated =
clearButtonLabel ??
t('features.publicForm.components.fields.dropdown.clearSelection')

const {
toggleMenu,
Expand Down Expand Up @@ -313,11 +326,11 @@ export const MultiSelectProvider = ({
selectItem,
highlightedIndex,
items: filteredItems,
nothingFoundLabel,
nothingFoundLabel: nothingFoundLabelTranslated,
inputValue,
isSearchable,
name,
clearButtonLabel,
clearButtonLabel: clearButtonLabelTranslated,
placeholder: dynamicPlaceholder,
styles,
isFocused,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const SingleSelectProvider = ({
name,
filter = defaultFilter,
placeholder: placeholderProp,
clearButtonLabel = 'Clear selection',
clearButtonLabel,
isClearable = true,
isSearchable = true,
initialIsOpen,
Expand Down Expand Up @@ -94,6 +94,10 @@ export const SingleSelectProvider = ({
'features.publicForm.components.fields.dropdown.nothingFound',
)

const clearButtonLabelTranslated =
clearButtonLabel ??
t('features.publicForm.components.fields.dropdown.clearSelection')

const getFilteredItems = useCallback(
(filterValue?: string) =>
filterValue ? filter(items, filterValue) : items,
Expand Down Expand Up @@ -274,7 +278,7 @@ export const SingleSelectProvider = ({
isReadOnly,
isRequired,
name,
clearButtonLabel,
clearButtonLabel: clearButtonLabelTranslated,
placeholder,
styles,
isFocused,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ const textProps: TextProps = {
export const PreviewFormBanner = ({
isTemplate,
}: PreviewFormBannerProps): JSX.Element => {
const { t } = useTranslation()
const { t } = useTranslation('translation', {
keyPrefix: 'features.adminForm.previewFormBanner',
})
const { t: tCommon } = useTranslation()
const { formId, isPaymentEnabled } = usePublicFormContext()
const { data: { secretEnv } = {} } = useEnv()
const {
Expand Down Expand Up @@ -99,7 +102,7 @@ export const PreviewFormBanner = ({
mr={{ base: '0.5rem', md: '1rem' }}
/>
<Text textStyle="subhead-3">
{isTemplate ? 'Template Preview' : 'Form Preview'}
{isTemplate ? t('templatePreview') : t('formPreview')}
</Text>
</Flex>
{isTemplate ? (
Expand All @@ -111,35 +114,35 @@ export const PreviewFormBanner = ({
>
<Link
variant="standalone"
aria-label="Click to return to the admin dashboard"
aria-label={t('backToDashboardAriaLabel')}
as={ReactLink}
to={DASHBOARD_ROUTE}
>
Back to FormSG
{t('backToFormSG')}
</Link>
<Button
aria-label="Click to use this template"
aria-label={t('useTemplateAriaLabel')}
onClick={onModalOpen}
>
Use this template
{t('useTemplate')}
</Button>
</Stack>
<IconButton
color="primary.500"
variant="clear"
display={{ base: 'flex', md: 'none' }}
aria-label="Template preview actions"
aria-label={t('templateActionsAriaLabel')}
onClick={onDrawerOpen}
icon={<BiDotsHorizontalRounded />}
/>
</>
) : (
<Button
aria-label={t('features.common.editForm.ariaLabel')}
aria-label={tCommon('features.common.editForm.ariaLabel')}
as={ReactLink}
to={`${ADMINFORM_ROUTE}/${formId}`}
>
{t('features.common.editForm.text')}
{tCommon('features.common.editForm.text')}
</Button>
)}
</Flex>
Expand All @@ -165,7 +168,7 @@ export const PreviewFormBanner = ({
isFullWidth={true}
{...mobileDrawerButtonProps}
>
Use this template
{t('useTemplate')}
</Button>
<Divider />
<Button
Expand All @@ -174,7 +177,7 @@ export const PreviewFormBanner = ({
leftIcon={<BiArrowBack fontSize="1.25rem" />}
{...mobileDrawerButtonProps}
>
Back to FormSG
{t('backToFormSG')}
</Button>
</DrawerBody>
</DrawerContent>
Expand All @@ -184,27 +187,20 @@ export const PreviewFormBanner = ({
<Flex backgroundColor="neutral.900">
{secretEnv === 'production' ? (
<Text {...textProps}>
To test your payment form, replicate this form on our{' '}
{t('paymentWarning.production.prefix')}
<Link isExternal color="white" href={FORMSG_UAT}>
testing platform.
{t('paymentWarning.production.linkText')}
</Link>
</Text>
) : (
<Text {...textProps}>
You will not be able to make a test payment, or view submitted
answers or attachments in Form Preview mode. Open your form to
make a test payment or form submission.
</Text>
<Text {...textProps}>{t('paymentWarning.nonProduction')}</Text>
)}
</Flex>
)}
{!isPaymentEnabled && (
<Flex backgroundColor="neutral.900">
{!(secretEnv === 'production') && (
<Text {...textProps}>
You will not be able to view submitted answers or attachments in
Form Preview mode. Open your form to test a form submission.
</Text>
<Text {...textProps}>{t('previewWarning.withoutPayment')}</Text>
)}
</Flex>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTranslation } from 'react-i18next'
import { Flex, Portal, Text } from '@chakra-ui/react'

import { NextAndBackButtonGroup } from '~components/Button'
Expand All @@ -12,20 +13,22 @@ const MagicFormBuilderAcceptDeny = ({
onAccept: () => void
onDeny: () => void
}) => {
const { t } = useTranslation('translation', {
keyPrefix: 'features.adminForm.magicFormBuilder.acceptDeny',
})

return isOpen ? (
<Portal>
<BottomHugBox>
<Flex direction="column" gap="1rem">
<Text textStyle="h6">
The created fields have been saved.
<br />
Keep them?
<Text textStyle="h6" whiteSpace="pre-line">
{t('message')}
</Text>
<NextAndBackButtonGroup
handleBack={onDeny}
handleNext={onAccept}
nextButtonLabel="Yes, keep them"
backButtonLabel="No, delete them"
nextButtonLabel={t('keepButton')}
backButtonLabel={t('deleteButton')}
/>
</Flex>
</BottomHugBox>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTranslation } from 'react-i18next'
import { BiSolidMagicWand } from 'react-icons/bi'

import Button from '~components/Button'
Expand All @@ -7,14 +8,18 @@ const MagicFormBuilderButton = ({
}: {
onClick: () => void
}): JSX.Element => {
const { t } = useTranslation('translation', {
keyPrefix: 'features.adminForm.magicFormBuilder.button',
})

return (
<Button
maxW="100%"
rightIcon={<BiSolidMagicWand fontSize="1.5rem" />}
onClick={onClick}
isTruncated
>
Create fields with AI
{t('createFields')}
</Button>
)
}
Expand Down
Loading
Loading