From 93ee4e784535598841f026e0ddfedb12f29ccb11 Mon Sep 17 00:00:00 2001 From: lunars97 Date: Thu, 12 Oct 2023 16:42:22 +0200 Subject: [PATCH 1/9] 1233: Implement lists as actual list --- native/src/components/SearchListItem.tsx | 6 +- native/src/routes/CityNotCooperating.tsx | 77 ++++++++++++++++++------ 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/native/src/components/SearchListItem.tsx b/native/src/components/SearchListItem.tsx index baf48ce1ee..082c320ccb 100644 --- a/native/src/components/SearchListItem.tsx +++ b/native/src/components/SearchListItem.tsx @@ -9,6 +9,7 @@ import { contentDirection } from '../constants/contentDirection' import { PageResourceCacheStateType } from '../utils/DataContainer' import { getCachedThumbnail } from './Categories' import { CategoryThumbnail } from './CategoryListItem' +import List from './List' import Pressable from './base/Pressable' const FlexStyledLink = styled(Pressable)` @@ -85,7 +86,8 @@ const SearchListItem = ({ }} /> ) - return ( + + const SearchList = ( onItemPress(category)}> @@ -100,6 +102,8 @@ const SearchListItem = ({ ) + + return category} /> } export default memo(SearchListItem) diff --git a/native/src/routes/CityNotCooperating.tsx b/native/src/routes/CityNotCooperating.tsx index f91e8f9cd9..93d5ef631c 100644 --- a/native/src/routes/CityNotCooperating.tsx +++ b/native/src/routes/CityNotCooperating.tsx @@ -3,13 +3,15 @@ import React, { ReactElement, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components/native' +import List from '../components/List' import Icon from '../components/base/Icon' import TextButton from '../components/base/TextButton' import buildConfig, { buildConfigAssets } from '../constants/buildConfig' -const Container = styled.ScrollView` +const Container = styled.View` display: flex; - padding: 30px; + flex: 1; + padding: 30px 30px 0 30px; ` const Heading = styled.Text` @@ -30,6 +32,7 @@ const ListHeading = styled(Heading)` ` const ListItem = styled.View` + top: -130px; flex-direction: row; margin: 10px 0; align-items: center; @@ -53,30 +56,51 @@ const StepExplanation = styled.Text` ` const StyledButton = styled(TextButton)` + top: -130px; z-index: 1; margin: 15px auto 0; width: 70%; ` const TemplateText = styled.Text` - top: -20px; + top: -150px; border: 1px solid ${props => props.theme.colors.themeColor}; padding: 50px 30px 30px; margin-bottom: 40px; ` const StyledIcon = styled(Icon)` + margin: 10px 0; align-self: center; width: 50%; - height: 20%; + height: 30%; ` +type Step = { + number: string + id: string + explanation: string +} + const CityNotCooperating = (): ReactElement | null => { const { t } = useTranslation('cityNotCooperating') const [isCopied, setIsCopied] = useState(false) const template = buildConfig().featureFlags.cityNotCooperatingTemplate const CityNotCooperatingIcon = buildConfigAssets().CityNotCooperatingIcon + const steps: Step[] = [ + { + id: '1', + number: '1', + explanation: 'findOutMail', + }, + { + id: '2', + number: '2', + explanation: 'sendText', + }, + ] + if (!template) { return null } @@ -86,24 +110,43 @@ const CityNotCooperating = (): ReactElement | null => { setIsCopied(true) } - return ( - - {t('callToAction')} + const renderStepsList = ({ item }: { item: Step }) => ( + + {item.number} + {t(item.explanation)} + + ) + const CooperationHeader = ( + <> + {t('callToAction')} {t('explanation')} {CityNotCooperatingIcon && } {t('whatToDo')} - - 1 - {t('findOutMail')} - - - 2 - {t('sendText')} - - - + + ) + + const CooperationFooter = ( + <> + {template} + + ) + + return ( + + item.id} + /> ) } From e5c0a92e064d3728109eda6820797696ab53b0a7 Mon Sep 17 00:00:00 2001 From: lunars97 Date: Sun, 15 Oct 2023 22:40:23 +0200 Subject: [PATCH 2/9] 1233: ts error --- native/src/components/SearchListItem.tsx | 4 ++-- native/src/routes/CityNotCooperating.tsx | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/native/src/components/SearchListItem.tsx b/native/src/components/SearchListItem.tsx index 082c320ccb..28a25dccec 100644 --- a/native/src/components/SearchListItem.tsx +++ b/native/src/components/SearchListItem.tsx @@ -7,7 +7,7 @@ import { CategoryModel, getExcerpt, normalizeString } from 'api-client' import { SEARCH_PREVIEW_MAX_CHARS } from '../constants' import { contentDirection } from '../constants/contentDirection' import { PageResourceCacheStateType } from '../utils/DataContainer' -import { getCachedThumbnail } from './Categories' +import categories, { getCachedThumbnail } from './Categories' import { CategoryThumbnail } from './CategoryListItem' import List from './List' import Pressable from './base/Pressable' @@ -103,7 +103,7 @@ const SearchListItem = ({ ) - return category} /> + return category} Header={SearchList} /> } export default memo(SearchListItem) diff --git a/native/src/routes/CityNotCooperating.tsx b/native/src/routes/CityNotCooperating.tsx index 93d5ef631c..4351e54cd9 100644 --- a/native/src/routes/CityNotCooperating.tsx +++ b/native/src/routes/CityNotCooperating.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next' import styled from 'styled-components/native' import List from '../components/List' +import NothingFound from '../components/NothingFound' import Icon from '../components/base/Icon' import TextButton from '../components/base/TextButton' import buildConfig, { buildConfigAssets } from '../constants/buildConfig' @@ -110,7 +111,7 @@ const CityNotCooperating = (): ReactElement | null => { setIsCopied(true) } - const renderStepsList = ({ item }: { item: Step }) => ( + const renderStepsList = ({ item }: { item: Step; index: number }) => ( {item.number} {t(item.explanation)} @@ -128,12 +129,7 @@ const CityNotCooperating = (): ReactElement | null => { const CooperationFooter = ( <> - + {template} ) @@ -141,11 +137,11 @@ const CityNotCooperating = (): ReactElement | null => { return ( item.id} + noItemsMessage={} /> ) From 5d4a98f0ab4d60335cf876d109fc9b820e9b2583 Mon Sep 17 00:00:00 2001 From: lunars97 Date: Mon, 23 Oct 2023 10:29:35 +0200 Subject: [PATCH 3/9] 1233: linting error is resolved --- native/src/components/SearchListItem.tsx | 2 +- native/src/routes/CityNotCooperating.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native/src/components/SearchListItem.tsx b/native/src/components/SearchListItem.tsx index 28a25dccec..c1f6149e47 100644 --- a/native/src/components/SearchListItem.tsx +++ b/native/src/components/SearchListItem.tsx @@ -7,7 +7,7 @@ import { CategoryModel, getExcerpt, normalizeString } from 'api-client' import { SEARCH_PREVIEW_MAX_CHARS } from '../constants' import { contentDirection } from '../constants/contentDirection' import { PageResourceCacheStateType } from '../utils/DataContainer' -import categories, { getCachedThumbnail } from './Categories' +import { getCachedThumbnail } from './Categories' import { CategoryThumbnail } from './CategoryListItem' import List from './List' import Pressable from './base/Pressable' diff --git a/native/src/routes/CityNotCooperating.tsx b/native/src/routes/CityNotCooperating.tsx index 4351e54cd9..f70b90a10c 100644 --- a/native/src/routes/CityNotCooperating.tsx +++ b/native/src/routes/CityNotCooperating.tsx @@ -137,7 +137,7 @@ const CityNotCooperating = (): ReactElement | null => { return ( Date: Thu, 2 Nov 2023 01:04:58 +0100 Subject: [PATCH 4/9] 1233: additional changes to accessibility --- native/src/components/CategoryListItem.tsx | 25 ++++++++++++------- native/src/components/LayoutedScrollView.tsx | 6 +++-- native/src/components/List.tsx | 3 +++ native/src/components/SearchListItem.tsx | 4 ++- .../__tests__/SearchListItem.spec.tsx | 5 ++++ native/src/routes/SearchModal.tsx | 1 + 6 files changed, 32 insertions(+), 12 deletions(-) diff --git a/native/src/components/CategoryListItem.tsx b/native/src/components/CategoryListItem.tsx index 137e84562b..5974453e17 100644 --- a/native/src/components/CategoryListItem.tsx +++ b/native/src/components/CategoryListItem.tsx @@ -7,6 +7,8 @@ import { contentDirection, isContentDirectionReversalRequired } from '../constan import dimensions from '../constants/dimensions' import { LanguageResourceCacheStateType } from '../utils/DataContainer' import { getCachedThumbnail } from './Categories' +import List from './List' +import NothingFound from './NothingFound' import SimpleImage from './SimpleImage' import SubCategoryListItem from './SubCategoryListItem' import Pressable from './base/Pressable' @@ -82,15 +84,20 @@ const CategoryListItem = ({ - {subCategories.map(subCategory => ( - - ))} + ( + + )} + scrollEnabled={false} + noItemsMessage={} + /> ) diff --git a/native/src/components/LayoutedScrollView.tsx b/native/src/components/LayoutedScrollView.tsx index 1bbbbe8216..76fc9416cc 100644 --- a/native/src/components/LayoutedScrollView.tsx +++ b/native/src/components/LayoutedScrollView.tsx @@ -7,10 +7,11 @@ import Layout from './Layout' type LayoutedScrollViewProps = { children?: React.ReactNode refreshControl?: React.ReactElement + nestedScrollEnabled?: boolean } const LayoutedScrollView = (props: LayoutedScrollViewProps): ReactElement => { - const { children, refreshControl } = props + const { children, refreshControl, nestedScrollEnabled = true } = props return ( { refreshControl={refreshControl} contentContainerStyle={{ flexGrow: 1, - }}> + }} + nestedScrollEnabled={nestedScrollEnabled}> {children} diff --git a/native/src/components/List.tsx b/native/src/components/List.tsx index b3b8bc8174..107129c274 100644 --- a/native/src/components/List.tsx +++ b/native/src/components/List.tsx @@ -15,6 +15,7 @@ type ListProps = { renderItem: (props: { item: T; index: number }) => ReactElement Header?: ReactElement Footer?: ReactElement + scrollEnabled?: boolean refresh?: () => void onEndReached?: () => void } @@ -27,6 +28,7 @@ const List = ({ Footer, refresh, onEndReached, + scrollEnabled, }: ListProps): ReactElement => ( ({ paddingHorizontal: 10, }} onEndReachedThreshold={1} + scrollEnabled={scrollEnabled} /> ) diff --git a/native/src/components/SearchListItem.tsx b/native/src/components/SearchListItem.tsx index baf48ce1ee..583f025141 100644 --- a/native/src/components/SearchListItem.tsx +++ b/native/src/components/SearchListItem.tsx @@ -46,6 +46,7 @@ type SearchListItemProps = { contentWithoutHtml: string resourceCache: PageResourceCacheStateType onItemPress: (category: CategoryModel) => void + accessibilityLabel: string language: string query: string } @@ -55,6 +56,7 @@ const SearchListItem = ({ category, resourceCache, contentWithoutHtml, + accessibilityLabel, onItemPress, query, }: SearchListItemProps): ReactElement => { @@ -86,7 +88,7 @@ const SearchListItem = ({ /> ) return ( - onItemPress(category)}> + onItemPress(category)} accessibilityLabel={accessibilityLabel}> diff --git a/native/src/components/__tests__/SearchListItem.spec.tsx b/native/src/components/__tests__/SearchListItem.spec.tsx index 55b82172a2..e7a22b8452 100644 --- a/native/src/components/__tests__/SearchListItem.spec.tsx +++ b/native/src/components/__tests__/SearchListItem.spec.tsx @@ -14,6 +14,7 @@ jest.mock('react-native-webview', () => ({ describe('SearchListItem', () => { const cityModel = new CityModelBuilder(1).build()[0]! const language = new LanguageModelBuilder(1).build()[0]! + const accessibilityLabel = 'This is an example category label' const { categories: categoriesMapModel, resourceCache } = new CategoriesMapModelBuilder( cityModel.code, language.code, @@ -46,6 +47,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} + accessibilityLabel={accessibilityLabel} />, ) @@ -64,6 +66,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={category.title} + accessibilityLabel={accessibilityLabel} />, ) @@ -84,6 +87,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} + accessibilityLabel={accessibilityLabel} />, ) @@ -104,6 +108,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} + accessibilityLabel={accessibilityLabel} />, ) diff --git a/native/src/routes/SearchModal.tsx b/native/src/routes/SearchModal.tsx index 34e173104d..79de0c1880 100644 --- a/native/src/routes/SearchModal.tsx +++ b/native/src/routes/SearchModal.tsx @@ -102,6 +102,7 @@ const SearchModal = ({ contentWithoutHtml={item.contentWithoutHtml} language={languageCode} query={query} + accessibilityLabel={t(`Category ${item.category.title}`)} onItemPress={onItemPress} /> ) From f5d2d5d7ccd3d15e9421740b27403381c5c3083b Mon Sep 17 00:00:00 2001 From: lunars97 Date: Mon, 6 Nov 2023 15:18:25 +0100 Subject: [PATCH 5/9] 1233: improved accessibility on native and web --- native/src/components/CategoryListItem.tsx | 2 - native/src/components/List.tsx | 7 +++- native/src/components/SearchListItem.tsx | 6 +-- .../__tests__/SearchListItem.spec.tsx | 10 ++--- native/src/components/base/TextButton.tsx | 25 +++++++++++-- native/src/routes/CityNotCooperating.tsx | 27 +++++++++----- native/src/routes/SearchModal.tsx | 3 +- web/src/routes/CityNotCooperatingPage.tsx | 37 +++++++++++++------ 8 files changed, 81 insertions(+), 36 deletions(-) diff --git a/native/src/components/CategoryListItem.tsx b/native/src/components/CategoryListItem.tsx index 5974453e17..4910db9da7 100644 --- a/native/src/components/CategoryListItem.tsx +++ b/native/src/components/CategoryListItem.tsx @@ -8,7 +8,6 @@ import dimensions from '../constants/dimensions' import { LanguageResourceCacheStateType } from '../utils/DataContainer' import { getCachedThumbnail } from './Categories' import List from './List' -import NothingFound from './NothingFound' import SimpleImage from './SimpleImage' import SubCategoryListItem from './SubCategoryListItem' import Pressable from './base/Pressable' @@ -96,7 +95,6 @@ const CategoryListItem = ({ /> )} scrollEnabled={false} - noItemsMessage={} /> ) diff --git a/native/src/components/List.tsx b/native/src/components/List.tsx index 107129c274..cd63d18983 100644 --- a/native/src/components/List.tsx +++ b/native/src/components/List.tsx @@ -1,5 +1,5 @@ import React, { ReactElement } from 'react' -import { FlatList, RefreshControl } from 'react-native' +import { FlatList, RefreshControl, AccessibilityRole } from 'react-native' import styled from 'styled-components/native' const NoItemsMessage = styled.Text` @@ -11,11 +11,12 @@ const NoItemsMessage = styled.Text` type ListProps = { items: Array - noItemsMessage: ReactElement | string + noItemsMessage?: ReactElement | string renderItem: (props: { item: T; index: number }) => ReactElement Header?: ReactElement Footer?: ReactElement scrollEnabled?: boolean + accessibilityRole?: AccessibilityRole | undefined refresh?: () => void onEndReached?: () => void } @@ -27,6 +28,7 @@ const List = ({ Header, Footer, refresh, + accessibilityRole, onEndReached, scrollEnabled, }: ListProps): ReactElement => ( @@ -48,6 +50,7 @@ const List = ({ }} onEndReachedThreshold={1} scrollEnabled={scrollEnabled} + accessibilityRole={accessibilityRole} /> ) diff --git a/native/src/components/SearchListItem.tsx b/native/src/components/SearchListItem.tsx index 583f025141..b9bcc157c1 100644 --- a/native/src/components/SearchListItem.tsx +++ b/native/src/components/SearchListItem.tsx @@ -46,7 +46,7 @@ type SearchListItemProps = { contentWithoutHtml: string resourceCache: PageResourceCacheStateType onItemPress: (category: CategoryModel) => void - accessibilityLabel: string + accessibilityHint: string language: string query: string } @@ -56,7 +56,7 @@ const SearchListItem = ({ category, resourceCache, contentWithoutHtml, - accessibilityLabel, + accessibilityHint, onItemPress, query, }: SearchListItemProps): ReactElement => { @@ -88,7 +88,7 @@ const SearchListItem = ({ /> ) return ( - onItemPress(category)} accessibilityLabel={accessibilityLabel}> + onItemPress(category)} accessibilityHint={accessibilityHint}> diff --git a/native/src/components/__tests__/SearchListItem.spec.tsx b/native/src/components/__tests__/SearchListItem.spec.tsx index e7a22b8452..0f75a1d8b1 100644 --- a/native/src/components/__tests__/SearchListItem.spec.tsx +++ b/native/src/components/__tests__/SearchListItem.spec.tsx @@ -14,7 +14,7 @@ jest.mock('react-native-webview', () => ({ describe('SearchListItem', () => { const cityModel = new CityModelBuilder(1).build()[0]! const language = new LanguageModelBuilder(1).build()[0]! - const accessibilityLabel = 'This is an example category label' + const accessibilityHint = 'Navigates to the chosen item' const { categories: categoriesMapModel, resourceCache } = new CategoriesMapModelBuilder( cityModel.code, language.code, @@ -47,7 +47,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - accessibilityLabel={accessibilityLabel} + accessibilityHint={accessibilityHint} />, ) @@ -66,7 +66,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={category.title} - accessibilityLabel={accessibilityLabel} + accessibilityHint={accessibilityHint} />, ) @@ -87,7 +87,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - accessibilityLabel={accessibilityLabel} + accessibilityHint={accessibilityHint} />, ) @@ -108,7 +108,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - accessibilityLabel={accessibilityLabel} + accessibilityHint={accessibilityHint} />, ) diff --git a/native/src/components/base/TextButton.tsx b/native/src/components/base/TextButton.tsx index 36cf9ecdc9..0303bd9bca 100644 --- a/native/src/components/base/TextButton.tsx +++ b/native/src/components/base/TextButton.tsx @@ -1,5 +1,5 @@ import React, { ReactElement } from 'react' -import { StyleProp, ViewStyle } from 'react-native' +import { StyleProp, ViewStyle, AccessibilityRole } from 'react-native' import styled from 'styled-components/native' import Pressable from './Pressable' @@ -25,12 +25,31 @@ type TextButtonProps = { text: string onPress: () => Promise | void disabled?: boolean + accessible?: boolean + focusable?: boolean + accessibilityRole?: AccessibilityRole | undefined type?: 'primary' | 'clear' style?: StyleProp } -const TextButton = ({ text, onPress, disabled = false, type = 'primary', style }: TextButtonProps): ReactElement => ( - +const TextButton = ({ + text, + onPress, + disabled = false, + type = 'primary', + style, + accessible, + accessibilityRole, + focusable, +}: TextButtonProps): ReactElement => ( + {text} ) diff --git a/native/src/routes/CityNotCooperating.tsx b/native/src/routes/CityNotCooperating.tsx index f70b90a10c..4b2e09d084 100644 --- a/native/src/routes/CityNotCooperating.tsx +++ b/native/src/routes/CityNotCooperating.tsx @@ -12,13 +12,13 @@ import buildConfig, { buildConfigAssets } from '../constants/buildConfig' const Container = styled.View` display: flex; flex: 1; - padding: 30px 30px 0 30px; + margin: 30px 30px 0 30px; ` const Heading = styled.Text` font-family: ${props => props.theme.fonts.native.decorativeFontBold}; font-size: 18px; - padding: 20px 20px 40px; + margin: 20px 20px 30px; text-align: center; ` @@ -30,10 +30,10 @@ const ListHeading = styled(Heading)` align-self: flex-start; font-size: 15px; padding: 10px 0; + margin-bottom: -200px; ` const ListItem = styled.View` - top: -130px; flex-direction: row; margin: 10px 0; align-items: center; @@ -56,18 +56,22 @@ const StepExplanation = styled.Text` padding-bottom: 4px; ` +const FooterContainer = styled.View` + display: flex; + justify-content: flex-end; + margin-bottom: 330px; +` + const StyledButton = styled(TextButton)` - top: -130px; z-index: 1; margin: 15px auto 0; width: 70%; ` const TemplateText = styled.Text` - top: -150px; border: 1px solid ${props => props.theme.colors.themeColor}; padding: 50px 30px 30px; - margin-bottom: 40px; + margin-top: -20px; ` const StyledIcon = styled(Icon)` @@ -128,16 +132,21 @@ const CityNotCooperating = (): ReactElement | null => { ) const CooperationFooter = ( - <> - + + {template} - + ) return ( ) @@ -114,6 +114,7 @@ const SearchModal = ({ diff --git a/web/src/routes/CityNotCooperatingPage.tsx b/web/src/routes/CityNotCooperatingPage.tsx index 98ae4be7ca..a73a32c978 100644 --- a/web/src/routes/CityNotCooperatingPage.tsx +++ b/web/src/routes/CityNotCooperatingPage.tsx @@ -13,7 +13,7 @@ const Container = styled.div` flex-direction: column; ` -const Heading = styled.p` +const Heading = styled.h1` font-weight: 600; text-align: center; font-size: 1.4rem; @@ -34,14 +34,26 @@ const Icon = styled.img` align-self: center; ` -const ListHeading = styled(Heading)` +const ListHeading = styled.h2` padding: 0; + font-weight: 600; + text-align: center; font-size: ${props => props.theme.fonts.decorativeFontSize}; + font-family: ${props => props.theme.fonts.web.decorativeFont}; + white-space: pre-line; +` + +const ListItem = styled.ul` + display: flex; + flex-direction: column; + align-items: flex-start; + margin: -3px 0 0 -37px; + list-style: none; ` -const ListItem = styled.div` +const StepList = styled.li` display: flex; - align-items: center; + justify-content: row; ` const StepNumber = styled.div` @@ -54,7 +66,8 @@ const StepNumber = styled.div` ` const StepExplanation = styled(Text)` - padding: 0 10px; + padding: 0 5px 10px 10px; + line-height: 10px; ` const StyledButton = styled(TextButton)` @@ -106,12 +119,14 @@ const CityNotCooperatingPage = ({ languageCode }: CityNotCooperatingPageProps): {t('whatToDo')} - 1 - {t('findOutMail')} - - - 2 - {t('sendText')} + + 1 + {t('findOutMail')} + + + 2 + {t('sendText')} + {template} From 773d11899a3b9368b4cf398cd2c276ba10579784 Mon Sep 17 00:00:00 2001 From: lunars97 Date: Mon, 20 Nov 2023 15:26:09 +0100 Subject: [PATCH 6/9] 1233: Removed some unnessary props and renamed the file --- native/src/components/Categories.tsx | 4 +- ...{CategoryListItem.tsx => CategoryList.tsx} | 4 +- native/src/components/LayoutedScrollView.tsx | 7 +- native/src/components/List.tsx | 9 +- native/src/components/SearchListItem.tsx | 2 +- native/src/components/SubCategoryListItem.tsx | 2 +- ...istItem.spec.tsx => CategoryList.spec.tsx} | 6 +- .../__tests__/SearchListItem.spec.tsx | 2 +- native/src/components/base/TextButton.tsx | 20 +---- native/src/routes/CityNotCooperating.tsx | 86 ++++--------------- native/src/routes/SearchModal.tsx | 4 +- translations/translations.json | 2 + web/src/routes/CityNotCooperatingPage.tsx | 38 +++----- 13 files changed, 55 insertions(+), 131 deletions(-) rename native/src/components/{CategoryListItem.tsx => CategoryList.tsx} (98%) rename native/src/components/__tests__/{CategoryListItem.spec.tsx => CategoryList.spec.tsx} (91%) diff --git a/native/src/components/Categories.tsx b/native/src/components/Categories.tsx index 8ece483017..d5ef808579 100644 --- a/native/src/components/Categories.tsx +++ b/native/src/components/Categories.tsx @@ -9,7 +9,7 @@ import { URL_PREFIX } from '../constants/webview' import TileModel from '../models/TileModel' import testID from '../testing/testID' import { LanguageResourceCacheStateType, PageResourceCacheStateType } from '../utils/DataContainer' -import CategoryListItem from './CategoryListItem' +import CategoryList from './CategoryList' import OrganizationContentInfo from './OrganizationContentInfo' import Page from './Page' import Tiles from './Tiles' @@ -81,7 +81,7 @@ const Categories = ({ path={category.path} AfterContent={category.organization && } Footer={children.map(it => ( - ) -export default memo(CategoryListItem) +export default memo(CategoryList) diff --git a/native/src/components/LayoutedScrollView.tsx b/native/src/components/LayoutedScrollView.tsx index 76fc9416cc..0bcfc18f93 100644 --- a/native/src/components/LayoutedScrollView.tsx +++ b/native/src/components/LayoutedScrollView.tsx @@ -7,20 +7,19 @@ import Layout from './Layout' type LayoutedScrollViewProps = { children?: React.ReactNode refreshControl?: React.ReactElement - nestedScrollEnabled?: boolean } const LayoutedScrollView = (props: LayoutedScrollViewProps): ReactElement => { - const { children, refreshControl, nestedScrollEnabled = true } = props + const { children, refreshControl } = props return ( + }}> {children} diff --git a/native/src/components/List.tsx b/native/src/components/List.tsx index cbebd96c0b..51dd5e468b 100644 --- a/native/src/components/List.tsx +++ b/native/src/components/List.tsx @@ -1,5 +1,5 @@ import React, { ReactElement } from 'react' -import { FlatList, RefreshControl, AccessibilityRole } from 'react-native' +import { FlatList, RefreshControl } from 'react-native' import styled from 'styled-components/native' const NoItemsMessage = styled.Text` @@ -16,7 +16,7 @@ type ListProps = { Header?: ReactElement Footer?: ReactElement scrollEnabled?: boolean - accessibilityRole?: AccessibilityRole | undefined + accessibilityLabel?: string refresh?: () => void onEndReached?: () => void } @@ -28,7 +28,7 @@ const List = ({ Header, Footer, refresh, - accessibilityRole, + accessibilityLabel, onEndReached, scrollEnabled, }: ListProps): ReactElement => ( @@ -51,7 +51,8 @@ const List = ({ }} onEndReachedThreshold={1} scrollEnabled={scrollEnabled} - accessibilityRole={accessibilityRole} + accessibilityRole='list' + accessibilityLabel={accessibilityLabel} /> ) diff --git a/native/src/components/SearchListItem.tsx b/native/src/components/SearchListItem.tsx index b9bcc157c1..3d13d18f98 100644 --- a/native/src/components/SearchListItem.tsx +++ b/native/src/components/SearchListItem.tsx @@ -8,7 +8,7 @@ import { SEARCH_PREVIEW_MAX_CHARS } from '../constants' import { contentDirection } from '../constants/contentDirection' import { PageResourceCacheStateType } from '../utils/DataContainer' import { getCachedThumbnail } from './Categories' -import { CategoryThumbnail } from './CategoryListItem' +import { CategoryThumbnail } from './CategoryList' import Pressable from './base/Pressable' const FlexStyledLink = styled(Pressable)` diff --git a/native/src/components/SubCategoryListItem.tsx b/native/src/components/SubCategoryListItem.tsx index d50d086a46..13992321d2 100644 --- a/native/src/components/SubCategoryListItem.tsx +++ b/native/src/components/SubCategoryListItem.tsx @@ -6,7 +6,7 @@ import { CategoryModel } from 'api-client' import { contentDirection } from '../constants/contentDirection' import { PageResourceCacheStateType } from '../utils/DataContainer' import { getCachedThumbnail } from './Categories' -import { CategoryThumbnail } from './CategoryListItem' +import { CategoryThumbnail } from './CategoryList' import Pressable from './base/Pressable' const SubCategoryTitleContainer = styled.View<{ language: string }>` diff --git a/native/src/components/__tests__/CategoryListItem.spec.tsx b/native/src/components/__tests__/CategoryList.spec.tsx similarity index 91% rename from native/src/components/__tests__/CategoryListItem.spec.tsx rename to native/src/components/__tests__/CategoryList.spec.tsx index 7da54da82e..80bf0fbc61 100644 --- a/native/src/components/__tests__/CategoryListItem.spec.tsx +++ b/native/src/components/__tests__/CategoryList.spec.tsx @@ -3,14 +3,14 @@ import React from 'react' import { CategoriesMapModelBuilder, CityModelBuilder, LanguageModelBuilder } from 'api-client' import render from '../../testing/render' -import CategoryListItem from '../CategoryListItem' +import CategoryList from '../CategoryList' jest.mock('styled-components') jest.mock('react-native-webview', () => ({ default: () => jest.fn(), })) -describe('CategoryListItem', () => { +describe('CategoryList', () => { const cityModel = new CityModelBuilder(1).build()[0]! const language = new LanguageModelBuilder(1).build()[0]! const { categories: categoriesMapModel, resourceCache } = new CategoriesMapModelBuilder( @@ -29,7 +29,7 @@ describe('CategoryListItem', () => { it('should render category and subcategories', () => { const { getByText } = render( - ({ describe('SearchListItem', () => { const cityModel = new CityModelBuilder(1).build()[0]! const language = new LanguageModelBuilder(1).build()[0]! - const accessibilityHint = 'Navigates to the chosen item' + const accessibilityHint = 'Navigates to the chosen page' const { categories: categoriesMapModel, resourceCache } = new CategoriesMapModelBuilder( cityModel.code, language.code, diff --git a/native/src/components/base/TextButton.tsx b/native/src/components/base/TextButton.tsx index 0303bd9bca..fbe202ad93 100644 --- a/native/src/components/base/TextButton.tsx +++ b/native/src/components/base/TextButton.tsx @@ -1,5 +1,5 @@ import React, { ReactElement } from 'react' -import { StyleProp, ViewStyle, AccessibilityRole } from 'react-native' +import { StyleProp, ViewStyle } from 'react-native' import styled from 'styled-components/native' import Pressable from './Pressable' @@ -25,31 +25,17 @@ type TextButtonProps = { text: string onPress: () => Promise | void disabled?: boolean - accessible?: boolean - focusable?: boolean - accessibilityRole?: AccessibilityRole | undefined type?: 'primary' | 'clear' style?: StyleProp } -const TextButton = ({ - text, - onPress, - disabled = false, - type = 'primary', - style, - accessible, - accessibilityRole, - focusable, -}: TextButtonProps): ReactElement => ( +const TextButton = ({ text, onPress, disabled = false, type = 'primary', style }: TextButtonProps): ReactElement => ( + accessibilityRole='button'> {text} ) diff --git a/native/src/routes/CityNotCooperating.tsx b/native/src/routes/CityNotCooperating.tsx index 4b2e09d084..f91e8f9cd9 100644 --- a/native/src/routes/CityNotCooperating.tsx +++ b/native/src/routes/CityNotCooperating.tsx @@ -3,22 +3,19 @@ import React, { ReactElement, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components/native' -import List from '../components/List' -import NothingFound from '../components/NothingFound' import Icon from '../components/base/Icon' import TextButton from '../components/base/TextButton' import buildConfig, { buildConfigAssets } from '../constants/buildConfig' -const Container = styled.View` +const Container = styled.ScrollView` display: flex; - flex: 1; - margin: 30px 30px 0 30px; + padding: 30px; ` const Heading = styled.Text` font-family: ${props => props.theme.fonts.native.decorativeFontBold}; font-size: 18px; - margin: 20px 20px 30px; + padding: 20px 20px 40px; text-align: center; ` @@ -30,7 +27,6 @@ const ListHeading = styled(Heading)` align-self: flex-start; font-size: 15px; padding: 10px 0; - margin-bottom: -200px; ` const ListItem = styled.View` @@ -56,12 +52,6 @@ const StepExplanation = styled.Text` padding-bottom: 4px; ` -const FooterContainer = styled.View` - display: flex; - justify-content: flex-end; - margin-bottom: 330px; -` - const StyledButton = styled(TextButton)` z-index: 1; margin: 15px auto 0; @@ -69,43 +59,24 @@ const StyledButton = styled(TextButton)` ` const TemplateText = styled.Text` + top: -20px; border: 1px solid ${props => props.theme.colors.themeColor}; padding: 50px 30px 30px; - margin-top: -20px; + margin-bottom: 40px; ` const StyledIcon = styled(Icon)` - margin: 10px 0; align-self: center; width: 50%; - height: 30%; + height: 20%; ` -type Step = { - number: string - id: string - explanation: string -} - const CityNotCooperating = (): ReactElement | null => { const { t } = useTranslation('cityNotCooperating') const [isCopied, setIsCopied] = useState(false) const template = buildConfig().featureFlags.cityNotCooperatingTemplate const CityNotCooperatingIcon = buildConfigAssets().CityNotCooperatingIcon - const steps: Step[] = [ - { - id: '1', - number: '1', - explanation: 'findOutMail', - }, - { - id: '2', - number: '2', - explanation: 'sendText', - }, - ] - if (!template) { return null } @@ -115,43 +86,24 @@ const CityNotCooperating = (): ReactElement | null => { setIsCopied(true) } - const renderStepsList = ({ item }: { item: Step; index: number }) => ( - - {item.number} - {t(item.explanation)} - - ) - - const CooperationHeader = ( - <> + return ( + {t('callToAction')} + {t('explanation')} {CityNotCooperatingIcon && } {t('whatToDo')} - - ) - - const CooperationFooter = ( - - + + 1 + {t('findOutMail')} + + + 2 + {t('sendText')} + + + {template} - - ) - - return ( - - } - /> ) } diff --git a/native/src/routes/SearchModal.tsx b/native/src/routes/SearchModal.tsx index 15f3b4b2d4..67f11f13e6 100644 --- a/native/src/routes/SearchModal.tsx +++ b/native/src/routes/SearchModal.tsx @@ -101,8 +101,8 @@ const SearchModal = ({ resourceCache={resourceCache[item.category.path] ?? {}} contentWithoutHtml={item.contentWithoutHtml} language={languageCode} + accessibilityHint={t('itemHint')} query={query} - accessibilityHint={t(`It navigates to the description of the item`)} onItemPress={onItemPress} /> ) @@ -114,7 +114,7 @@ const SearchModal = ({ diff --git a/translations/translations.json b/translations/translations.json index 5da4d8e8fd..4b6ca5e86b 100644 --- a/translations/translations.json +++ b/translations/translations.json @@ -8368,6 +8368,8 @@ "de": { "nothingFound": "Es wurden leider keine passenden Ergebnisse gefunden.", "searchPlaceholder": "Suche", + "itemHint": "Es navigiert zur Beschreibung der Seite", + "searchResults": "Suchergebnisse", "pageTitle": "Suche", "delete": "Eingabe löschen" }, diff --git a/web/src/routes/CityNotCooperatingPage.tsx b/web/src/routes/CityNotCooperatingPage.tsx index a73a32c978..de1b616fa1 100644 --- a/web/src/routes/CityNotCooperatingPage.tsx +++ b/web/src/routes/CityNotCooperatingPage.tsx @@ -13,7 +13,7 @@ const Container = styled.div` flex-direction: column; ` -const Heading = styled.h1` +const Heading = styled.p` font-weight: 600; text-align: center; font-size: 1.4rem; @@ -34,26 +34,14 @@ const Icon = styled.img` align-self: center; ` -const ListHeading = styled.h2` +const ListHeading = styled(Heading)` padding: 0; - font-weight: 600; - text-align: center; font-size: ${props => props.theme.fonts.decorativeFontSize}; - font-family: ${props => props.theme.fonts.web.decorativeFont}; - white-space: pre-line; ` -const ListItem = styled.ul` +const ListItem = styled.div` display: flex; - flex-direction: column; - align-items: flex-start; - margin: -3px 0 0 -37px; - list-style: none; -` - -const StepList = styled.li` - display: flex; - justify-content: row; + align-items: center; ` const StepNumber = styled.div` @@ -66,8 +54,7 @@ const StepNumber = styled.div` ` const StepExplanation = styled(Text)` - padding: 0 5px 10px 10px; - line-height: 10px; + padding: 0 10px; ` const StyledButton = styled(TextButton)` @@ -119,14 +106,12 @@ const CityNotCooperatingPage = ({ languageCode }: CityNotCooperatingPageProps): {t('whatToDo')} - - 1 - {t('findOutMail')} - - - 2 - {t('sendText')} - + 1 + {t('findOutMail')} + + + 2 + {t('sendText')} {template} @@ -134,5 +119,4 @@ const CityNotCooperatingPage = ({ languageCode }: CityNotCooperatingPageProps): ) } - export default CityNotCooperatingPage From e992d4049670b5f6b6999f21b3acf84bb3d07526 Mon Sep 17 00:00:00 2001 From: lunars97 Date: Fri, 24 Nov 2023 18:34:48 +0100 Subject: [PATCH 7/9] 1233: implemented suggestion related to prop --- native/src/components/SearchListItem.tsx | 7 ++++--- .../src/components/__tests__/SearchListItem.spec.tsx | 11 ++++++----- native/src/routes/SearchModal.tsx | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/native/src/components/SearchListItem.tsx b/native/src/components/SearchListItem.tsx index 3d13d18f98..7db2137962 100644 --- a/native/src/components/SearchListItem.tsx +++ b/native/src/components/SearchListItem.tsx @@ -1,3 +1,4 @@ +import { TFunction } from 'i18next' import React, { memo, ReactElement } from 'react' import Highlighter from 'react-native-highlight-words' import styled, { useTheme } from 'styled-components/native' @@ -46,9 +47,9 @@ type SearchListItemProps = { contentWithoutHtml: string resourceCache: PageResourceCacheStateType onItemPress: (category: CategoryModel) => void - accessibilityHint: string language: string query: string + t: TFunction<'search'> } const SearchListItem = ({ @@ -56,9 +57,9 @@ const SearchListItem = ({ category, resourceCache, contentWithoutHtml, - accessibilityHint, onItemPress, query, + t, }: SearchListItemProps): ReactElement => { const theme = useTheme() const { title, thumbnail } = category @@ -88,7 +89,7 @@ const SearchListItem = ({ /> ) return ( - onItemPress(category)} accessibilityHint={accessibilityHint}> + onItemPress(category)} accessibilityHint={t('itemHint')}> diff --git a/native/src/components/__tests__/SearchListItem.spec.tsx b/native/src/components/__tests__/SearchListItem.spec.tsx index 2043a38ada..3895fc7968 100644 --- a/native/src/components/__tests__/SearchListItem.spec.tsx +++ b/native/src/components/__tests__/SearchListItem.spec.tsx @@ -1,3 +1,4 @@ +import { TFunction } from 'i18next' import React from 'react' import { ReactTestInstance } from 'react-test-renderer' @@ -14,7 +15,6 @@ jest.mock('react-native-webview', () => ({ describe('SearchListItem', () => { const cityModel = new CityModelBuilder(1).build()[0]! const language = new LanguageModelBuilder(1).build()[0]! - const accessibilityHint = 'Navigates to the chosen page' const { categories: categoriesMapModel, resourceCache } = new CategoriesMapModelBuilder( cityModel.code, language.code, @@ -22,6 +22,7 @@ describe('SearchListItem', () => { const categories = categoriesMapModel.toArray() const category = categories[1]! const contentWithoutHtml = parseHTML(category.content) + const t = ((key: string) => key) as TFunction const onItemPress = jest.fn() @@ -47,7 +48,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - accessibilityHint={accessibilityHint} + t={t} />, ) @@ -66,7 +67,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={category.title} - accessibilityHint={accessibilityHint} + t={t} />, ) @@ -87,7 +88,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - accessibilityHint={accessibilityHint} + t={t} />, ) @@ -108,7 +109,7 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - accessibilityHint={accessibilityHint} + t={t} />, ) diff --git a/native/src/routes/SearchModal.tsx b/native/src/routes/SearchModal.tsx index 67f11f13e6..f1117b1139 100644 --- a/native/src/routes/SearchModal.tsx +++ b/native/src/routes/SearchModal.tsx @@ -101,9 +101,9 @@ const SearchModal = ({ resourceCache={resourceCache[item.category.path] ?? {}} contentWithoutHtml={item.contentWithoutHtml} language={languageCode} - accessibilityHint={t('itemHint')} query={query} onItemPress={onItemPress} + t={t} /> ) From 23ab06b4f1407435f05de187837b4cfc2021954d Mon Sep 17 00:00:00 2001 From: lunars97 Date: Mon, 4 Dec 2023 13:51:33 +0100 Subject: [PATCH 8/9] 1233: added pluralization and implemented suggestions --- native/src/components/Categories.tsx | 4 ++-- native/src/components/SearchListItem.tsx | 9 ++++---- .../{CategoryList.tsx => SubCategoryList.tsx} | 22 +++++++++---------- native/src/components/SubCategoryListItem.tsx | 4 ++-- .../__tests__/SearchListItem.spec.tsx | 6 ----- ...List.spec.tsx => SubCategoryList.spec.tsx} | 6 ++--- native/src/routes/SearchModal.tsx | 3 +-- translations/translations.json | 5 +++-- web/src/routes/CityNotCooperatingPage.tsx | 1 + 9 files changed, 27 insertions(+), 33 deletions(-) rename native/src/components/{CategoryList.tsx => SubCategoryList.tsx} (84%) rename native/src/components/__tests__/{CategoryList.spec.tsx => SubCategoryList.spec.tsx} (92%) diff --git a/native/src/components/Categories.tsx b/native/src/components/Categories.tsx index d5ef808579..e33eced31b 100644 --- a/native/src/components/Categories.tsx +++ b/native/src/components/Categories.tsx @@ -9,9 +9,9 @@ import { URL_PREFIX } from '../constants/webview' import TileModel from '../models/TileModel' import testID from '../testing/testID' import { LanguageResourceCacheStateType, PageResourceCacheStateType } from '../utils/DataContainer' -import CategoryList from './CategoryList' import OrganizationContentInfo from './OrganizationContentInfo' import Page from './Page' +import SubCategoryList from './SubCategoryList' import Tiles from './Tiles' export type CategoriesProps = { @@ -81,7 +81,7 @@ const Categories = ({ path={category.path} AfterContent={category.organization && } Footer={children.map(it => ( - void language: string query: string - t: TFunction<'search'> } const SearchListItem = ({ @@ -59,8 +58,8 @@ const SearchListItem = ({ contentWithoutHtml, onItemPress, query, - t, }: SearchListItemProps): ReactElement => { + const { t } = useTranslation('search') const theme = useTheme() const { title, thumbnail } = category const excerpt = getExcerpt(contentWithoutHtml, { query, maxChars: SEARCH_PREVIEW_MAX_CHARS }) @@ -94,7 +93,7 @@ const SearchListItem = ({ {!!thumbnail && ( - + )} {Title} diff --git a/native/src/components/CategoryList.tsx b/native/src/components/SubCategoryList.tsx similarity index 84% rename from native/src/components/CategoryList.tsx rename to native/src/components/SubCategoryList.tsx index b804172516..ae0cca087d 100644 --- a/native/src/components/CategoryList.tsx +++ b/native/src/components/SubCategoryList.tsx @@ -21,7 +21,7 @@ const DirectionContainer = styled.View<{ language: string }>` flex-direction: ${props => contentDirection(props.language)}; ` -const CategoryEntryContainer = styled.View` +const SubCategoryEntryContainer = styled.View` flex: 1; flex-direction: column; align-self: center; @@ -35,13 +35,13 @@ const TitleDirectionContainer = styled.View<{ language: string }>` flex-direction: ${props => contentDirection(props.language)}; ` -const CategoryTitle = styled.Text<{ language: string }>` +const SubCategoryTitle = styled.Text<{ language: string }>` flex-direction: ${props => contentDirection(props.language)}; font-family: ${props => props.theme.fonts.native.decorativeFontBold}; color: ${props => props.theme.colors.textColor}; ` -export const CategoryThumbnail = styled(SimpleImage)<{ language: string }>` +export const SubCategoryThumbnail = styled(SimpleImage)<{ language: string }>` align-self: center; flex-shrink: 0; width: ${dimensions.categoryListItem.iconSize}px; @@ -52,7 +52,7 @@ export const CategoryThumbnail = styled(SimpleImage)<{ language: string }>` isContentDirectionReversalRequired(props.language) ? dimensions.categoryListItem.margin : 0}px; ` -type CategoryListItemProps = { +type SubCategoryListProps = { category: CategoryModel subCategories: CategoryModel[] resourceCache: LanguageResourceCacheStateType @@ -60,27 +60,27 @@ type CategoryListItemProps = { language: string } -const CategoryList = ({ +const SubCategoryList = ({ language, category, subCategories, resourceCache, onItemPress, -}: CategoryListItemProps): ReactElement => ( +}: SubCategoryListProps): ReactElement => ( <> onItemPress({ path: category.path })}> - + {!!category.thumbnail && ( - )} - {category.title} + {category.title} - + ) -export default memo(CategoryList) +export default memo(SubCategoryList) diff --git a/native/src/components/SubCategoryListItem.tsx b/native/src/components/SubCategoryListItem.tsx index 13992321d2..703f97ba27 100644 --- a/native/src/components/SubCategoryListItem.tsx +++ b/native/src/components/SubCategoryListItem.tsx @@ -6,7 +6,7 @@ import { CategoryModel } from 'api-client' import { contentDirection } from '../constants/contentDirection' import { PageResourceCacheStateType } from '../utils/DataContainer' import { getCachedThumbnail } from './Categories' -import { CategoryThumbnail } from './CategoryList' +import { SubCategoryThumbnail } from './SubCategoryList' import Pressable from './base/Pressable' const SubCategoryTitleContainer = styled.View<{ language: string }>` @@ -45,7 +45,7 @@ const SubCategoryListItem = ({ onItemPress(subCategory)} language={language}> {!!subCategory.thumbnail && ( - + )} {subCategory.title} diff --git a/native/src/components/__tests__/SearchListItem.spec.tsx b/native/src/components/__tests__/SearchListItem.spec.tsx index 3895fc7968..55b82172a2 100644 --- a/native/src/components/__tests__/SearchListItem.spec.tsx +++ b/native/src/components/__tests__/SearchListItem.spec.tsx @@ -1,4 +1,3 @@ -import { TFunction } from 'i18next' import React from 'react' import { ReactTestInstance } from 'react-test-renderer' @@ -22,7 +21,6 @@ describe('SearchListItem', () => { const categories = categoriesMapModel.toArray() const category = categories[1]! const contentWithoutHtml = parseHTML(category.content) - const t = ((key: string) => key) as TFunction const onItemPress = jest.fn() @@ -48,7 +46,6 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - t={t} />, ) @@ -67,7 +64,6 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={category.title} - t={t} />, ) @@ -88,7 +84,6 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - t={t} />, ) @@ -109,7 +104,6 @@ describe('SearchListItem', () => { onItemPress={onItemPress} language={language.code} query={query} - t={t} />, ) diff --git a/native/src/components/__tests__/CategoryList.spec.tsx b/native/src/components/__tests__/SubCategoryList.spec.tsx similarity index 92% rename from native/src/components/__tests__/CategoryList.spec.tsx rename to native/src/components/__tests__/SubCategoryList.spec.tsx index 80bf0fbc61..1c19ecf236 100644 --- a/native/src/components/__tests__/CategoryList.spec.tsx +++ b/native/src/components/__tests__/SubCategoryList.spec.tsx @@ -3,14 +3,14 @@ import React from 'react' import { CategoriesMapModelBuilder, CityModelBuilder, LanguageModelBuilder } from 'api-client' import render from '../../testing/render' -import CategoryList from '../CategoryList' +import SubCategoryList from '../SubCategoryList' jest.mock('styled-components') jest.mock('react-native-webview', () => ({ default: () => jest.fn(), })) -describe('CategoryList', () => { +describe('SubCategoryList', () => { const cityModel = new CityModelBuilder(1).build()[0]! const language = new LanguageModelBuilder(1).build()[0]! const { categories: categoriesMapModel, resourceCache } = new CategoriesMapModelBuilder( @@ -29,7 +29,7 @@ describe('CategoryList', () => { it('should render category and subcategories', () => { const { getByText } = render( - ) @@ -115,7 +114,7 @@ const SearchModal = ({ diff --git a/translations/translations.json b/translations/translations.json index 2762e1711b..b94a89b219 100644 --- a/translations/translations.json +++ b/translations/translations.json @@ -8412,8 +8412,9 @@ "de": { "nothingFound": "Es wurden leider keine passenden Ergebnisse gefunden.", "searchPlaceholder": "Suche", - "itemHint": "Es navigiert zur Beschreibung der Seite", - "searchResults": "Suchergebnisse", + "itemHint": "Suchergebnis öffnen", + "searchResult": "{{count}} Suchergebnis", + "searchResult_other": "{{count}} Suchergebnisse", "pageTitle": "Suche", "delete": "Eingabe löschen" }, diff --git a/web/src/routes/CityNotCooperatingPage.tsx b/web/src/routes/CityNotCooperatingPage.tsx index de1b616fa1..98ae4be7ca 100644 --- a/web/src/routes/CityNotCooperatingPage.tsx +++ b/web/src/routes/CityNotCooperatingPage.tsx @@ -119,4 +119,5 @@ const CityNotCooperatingPage = ({ languageCode }: CityNotCooperatingPageProps): ) } + export default CityNotCooperatingPage From bcee709289f19437c0f6add134e9e41e488029df Mon Sep 17 00:00:00 2001 From: lunars97 Date: Tue, 5 Dec 2023 11:07:13 +0100 Subject: [PATCH 9/9] 1233: added translation and implemented suggestions --- native/src/components/Categories.tsx | 28 ++++++++++++------- ...bCategoryList.tsx => CategoryListItem.tsx} | 22 +++++++-------- native/src/components/LayoutedScrollView.tsx | 2 ++ native/src/components/SearchListItem.tsx | 4 +-- native/src/components/SubCategoryListItem.tsx | 4 +-- ...ist.spec.tsx => CategoryListItem.spec.tsx} | 6 ++-- native/src/routes/SearchModal.tsx | 2 +- translations/translations.json | 15 ++++++++-- 8 files changed, 52 insertions(+), 31 deletions(-) rename native/src/components/{SubCategoryList.tsx => CategoryListItem.tsx} (84%) rename native/src/components/__tests__/{SubCategoryList.spec.tsx => CategoryListItem.spec.tsx} (91%) diff --git a/native/src/components/Categories.tsx b/native/src/components/Categories.tsx index e33eced31b..e52610b4da 100644 --- a/native/src/components/Categories.tsx +++ b/native/src/components/Categories.tsx @@ -9,9 +9,10 @@ import { URL_PREFIX } from '../constants/webview' import TileModel from '../models/TileModel' import testID from '../testing/testID' import { LanguageResourceCacheStateType, PageResourceCacheStateType } from '../utils/DataContainer' +import SubCategoryList from './CategoryListItem' +import List from './List' import OrganizationContentInfo from './OrganizationContentInfo' import Page from './Page' -import SubCategoryList from './SubCategoryList' import Tiles from './Tiles' export type CategoriesProps = { @@ -80,16 +81,23 @@ const Categories = ({ language={language} path={category.path} AfterContent={category.organization && } - Footer={children.map(it => ( - ( + + )} + // Fixes VirtualizedLists nesting error + scrollEnabled={false} /> - ))} + } /> ) } diff --git a/native/src/components/SubCategoryList.tsx b/native/src/components/CategoryListItem.tsx similarity index 84% rename from native/src/components/SubCategoryList.tsx rename to native/src/components/CategoryListItem.tsx index ae0cca087d..4910db9da7 100644 --- a/native/src/components/SubCategoryList.tsx +++ b/native/src/components/CategoryListItem.tsx @@ -21,7 +21,7 @@ const DirectionContainer = styled.View<{ language: string }>` flex-direction: ${props => contentDirection(props.language)}; ` -const SubCategoryEntryContainer = styled.View` +const CategoryEntryContainer = styled.View` flex: 1; flex-direction: column; align-self: center; @@ -35,13 +35,13 @@ const TitleDirectionContainer = styled.View<{ language: string }>` flex-direction: ${props => contentDirection(props.language)}; ` -const SubCategoryTitle = styled.Text<{ language: string }>` +const CategoryTitle = styled.Text<{ language: string }>` flex-direction: ${props => contentDirection(props.language)}; font-family: ${props => props.theme.fonts.native.decorativeFontBold}; color: ${props => props.theme.colors.textColor}; ` -export const SubCategoryThumbnail = styled(SimpleImage)<{ language: string }>` +export const CategoryThumbnail = styled(SimpleImage)<{ language: string }>` align-self: center; flex-shrink: 0; width: ${dimensions.categoryListItem.iconSize}px; @@ -52,7 +52,7 @@ export const SubCategoryThumbnail = styled(SimpleImage)<{ language: string }>` isContentDirectionReversalRequired(props.language) ? dimensions.categoryListItem.margin : 0}px; ` -type SubCategoryListProps = { +type CategoryListItemProps = { category: CategoryModel subCategories: CategoryModel[] resourceCache: LanguageResourceCacheStateType @@ -60,27 +60,27 @@ type SubCategoryListProps = { language: string } -const SubCategoryList = ({ +const CategoryListItem = ({ language, category, subCategories, resourceCache, onItemPress, -}: SubCategoryListProps): ReactElement => ( +}: CategoryListItemProps): ReactElement => ( <> onItemPress({ path: category.path })}> - + {!!category.thumbnail && ( - )} - {category.title} + {category.title} - + ) -export default memo(SubCategoryList) +export default memo(CategoryListItem) diff --git a/native/src/components/LayoutedScrollView.tsx b/native/src/components/LayoutedScrollView.tsx index 0bcfc18f93..22c102b5f1 100644 --- a/native/src/components/LayoutedScrollView.tsx +++ b/native/src/components/LayoutedScrollView.tsx @@ -15,6 +15,8 @@ const LayoutedScrollView = (props: LayoutedScrollViewProps): ReactElement => { {!!thumbnail && ( - + )} {Title} diff --git a/native/src/components/SubCategoryListItem.tsx b/native/src/components/SubCategoryListItem.tsx index 703f97ba27..d50d086a46 100644 --- a/native/src/components/SubCategoryListItem.tsx +++ b/native/src/components/SubCategoryListItem.tsx @@ -6,7 +6,7 @@ import { CategoryModel } from 'api-client' import { contentDirection } from '../constants/contentDirection' import { PageResourceCacheStateType } from '../utils/DataContainer' import { getCachedThumbnail } from './Categories' -import { SubCategoryThumbnail } from './SubCategoryList' +import { CategoryThumbnail } from './CategoryListItem' import Pressable from './base/Pressable' const SubCategoryTitleContainer = styled.View<{ language: string }>` @@ -45,7 +45,7 @@ const SubCategoryListItem = ({ onItemPress(subCategory)} language={language}> {!!subCategory.thumbnail && ( - + )} {subCategory.title} diff --git a/native/src/components/__tests__/SubCategoryList.spec.tsx b/native/src/components/__tests__/CategoryListItem.spec.tsx similarity index 91% rename from native/src/components/__tests__/SubCategoryList.spec.tsx rename to native/src/components/__tests__/CategoryListItem.spec.tsx index 1c19ecf236..7da54da82e 100644 --- a/native/src/components/__tests__/SubCategoryList.spec.tsx +++ b/native/src/components/__tests__/CategoryListItem.spec.tsx @@ -3,14 +3,14 @@ import React from 'react' import { CategoriesMapModelBuilder, CityModelBuilder, LanguageModelBuilder } from 'api-client' import render from '../../testing/render' -import SubCategoryList from '../SubCategoryList' +import CategoryListItem from '../CategoryListItem' jest.mock('styled-components') jest.mock('react-native-webview', () => ({ default: () => jest.fn(), })) -describe('SubCategoryList', () => { +describe('CategoryListItem', () => { const cityModel = new CityModelBuilder(1).build()[0]! const language = new LanguageModelBuilder(1).build()[0]! const { categories: categoriesMapModel, resourceCache } = new CategoriesMapModelBuilder( @@ -29,7 +29,7 @@ describe('SubCategoryList', () => { it('should render category and subcategories', () => { const { getByText } = render( - diff --git a/translations/translations.json b/translations/translations.json index b94a89b219..22fae182ed 100644 --- a/translations/translations.json +++ b/translations/translations.json @@ -8413,8 +8413,12 @@ "nothingFound": "Es wurden leider keine passenden Ergebnisse gefunden.", "searchPlaceholder": "Suche", "itemHint": "Suchergebnis öffnen", - "searchResult": "{{count}} Suchergebnis", - "searchResult_other": "{{count}} Suchergebnisse", + "searchResultsCount_zero": "0 Suchergebnisse", + "searchResultsCount_one": "1 Suchergebnis", + "searchResultsCount_two": "2 Suchergebnisse", + "searchResultsCount_few": "{{count}} Suchergebnisse", + "searchResultsCount_many": "{{count}} Suchergebnisse", + "searchResultsCount_other": "{{count}} Suchergebnisse", "pageTitle": "Suche", "delete": "Eingabe löschen" }, @@ -8457,6 +8461,13 @@ "en": { "nothingFound": "Sorry, we could not find any matching results.", "searchPlaceholder": "Search", + "itemHint": "View search result", + "searchResultsCount_zero": "0 search results", + "searchResultsCount_one": "1 search result", + "searchResultsCount_two": "2 search results", + "searchResultsCount_few": "{{count}} search results", + "searchResultsCount_many": "{{count}} search results", + "searchResultsCount_other": "{{count}} search results", "pageTitle": "Search", "delete": "Delete input" },