From 3b7894e89202e5706d1ac08fe925c242bc003d3f Mon Sep 17 00:00:00 2001 From: Ben Furber Date: Tue, 21 Jan 2025 17:17:43 +0000 Subject: [PATCH] chore: tidy-up further category typing --- .../src/CardProfile/CardDetailsFallback.tsx | 6 +-- .../src/Category/Category.stories.tsx | 4 +- packages/components/src/Category/Category.tsx | 7 ++-- .../CategoryVerticalList.stories.tsx | 38 +++++++++---------- .../CategoryVerticalList.tsx | 20 +++++----- .../src/ProfileTagsList/ProfileTagsList.tsx | 4 +- shared/models/category.ts | 8 ++-- shared/models/document.ts | 10 ++--- src/models/question.model.ts | 8 ++-- src/pages/Question/QuestionListHeader.tsx | 6 +-- src/pages/Question/QuestionPage.test.tsx | 2 +- src/pages/Question/question.service.ts | 4 +- src/routes/api.categories.$type.ts | 18 ++++++--- src/test/factories/Category.ts | 6 +-- src/test/factories/Question.ts | 2 +- 15 files changed, 76 insertions(+), 67 deletions(-) diff --git a/packages/components/src/CardProfile/CardDetailsFallback.tsx b/packages/components/src/CardProfile/CardDetailsFallback.tsx index b853603e7f..80be60098d 100644 --- a/packages/components/src/CardProfile/CardDetailsFallback.tsx +++ b/packages/components/src/CardProfile/CardDetailsFallback.tsx @@ -4,7 +4,7 @@ import { Category } from '../Category/Category' import { MemberBadge } from '../MemberBadge/MemberBadge' import { Username } from '../Username/Username' -import type { DBCategory, IMapPin } from 'oa-shared' +import type { Category as CategoryType, IMapPin } from 'oa-shared' interface IProps { item: IMapPin @@ -26,7 +26,7 @@ export const CardDetailsFallback = ({ item, isLink }: IProps) => { /> {subType && ( { )} {type === 'member' && ( = () => ( category={ { name: 'Label', - } as DBCategory + } as CategoryType } /> ) diff --git a/packages/components/src/Category/Category.tsx b/packages/components/src/Category/Category.tsx index b696a92a44..811734c87b 100644 --- a/packages/components/src/Category/Category.tsx +++ b/packages/components/src/Category/Category.tsx @@ -1,18 +1,19 @@ import { Flex, Text } from 'theme-ui' -import type { DBCategory } from 'oa-shared' +import type { Category as CategoryType } from 'oa-shared' import type { ThemeUIStyleObject } from 'theme-ui' type OldICategory = { label: string } export interface Props { - category: DBCategory | OldICategory + category: CategoryType | OldICategory sx?: ThemeUIStyleObject | undefined } export const Category = (props: Props) => { const { category, sx } = props - const name = (category as DBCategory).name || (category as OldICategory).label + const name = + (category as CategoryType).name || (category as OldICategory).label return ( diff --git a/packages/components/src/CategoryVerticalList/CategoryVerticalList.stories.tsx b/packages/components/src/CategoryVerticalList/CategoryVerticalList.stories.tsx index b122ceabe4..555d39fb80 100644 --- a/packages/components/src/CategoryVerticalList/CategoryVerticalList.stories.tsx +++ b/packages/components/src/CategoryVerticalList/CategoryVerticalList.stories.tsx @@ -3,7 +3,7 @@ import { useState } from 'react' import { CategoryVerticalList } from './CategoryVerticalList' import type { Meta, StoryFn } from '@storybook/react' -import type { ContentTypes, DBCategory, ICategory } from 'oa-shared' +import type { Category, ContentTypes, ICategory } from 'oa-shared' export default { title: 'Components/CategoryVerticalList', @@ -12,43 +12,43 @@ export default { const allCategoriesForPreciousPlastic = [ { - created_at: new Date('2024-12-03T18:03:51.313Z'), + createdAt: new Date('2024-12-03T18:03:51.313Z'), id: 1, name: 'Guides', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-01T18:03:51.313Z'), + createdAt: new Date('2022-12-01T18:03:51.313Z'), id: 2, name: 'Machines', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 3, name: 'Moulds', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 4, name: 'Products', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 5, name: 'Starter Kits', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-04T18:03:51.313Z'), + createdAt: new Date('2022-12-04T18:03:51.313Z'), id: 6, name: 'Recycling', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-05T18:03:51.313Z'), + createdAt: new Date('2022-12-05T18:03:51.313Z'), id: 7, _modified: '2022-12-03T18:03:51.313Z', name: 'From the Team', @@ -58,31 +58,31 @@ const allCategoriesForPreciousPlastic = [ const allCategoriesForProjectKamp = [ { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 8, name: 'Construction', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 9, name: 'Food', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 10, name: 'Landscape', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 11, name: 'Other', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 12, name: 'Utilities', type: 'questions' as ContentTypes, @@ -91,7 +91,7 @@ const allCategoriesForProjectKamp = [ export const Basic: StoryFn = () => { const [activeCategory, setActiveCategory] = useState< - DBCategory | ICategory | null + Category | ICategory | null >(null) const allCategories = [ ...allCategoriesForPreciousPlastic, @@ -111,23 +111,23 @@ export const Basic: StoryFn = () => { export const WhenGlyphNotPresent: StoryFn = () => { const [activeCategory, setActiveCategory] = useState< - DBCategory | ICategory | null + Category | ICategory | null >(null) const noGlyphCategories = [ { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 13, name: 'No Glphy A', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 14, name: 'No Glphy B', type: 'questions' as ContentTypes, }, { - created_at: new Date('2022-12-03T18:03:51.313Z'), + createdAt: new Date('2022-12-03T18:03:51.313Z'), id: 15, name: 'No Glphy C', type: 'questions' as ContentTypes, @@ -147,7 +147,7 @@ export const WhenGlyphNotPresent: StoryFn = () => { export const OnlyOne: StoryFn = () => { const [activeCategory, setActiveCategory] = useState< - DBCategory | ICategory | null + Category | ICategory | null >(null) const twoCategories = [ diff --git a/packages/components/src/CategoryVerticalList/CategoryVerticalList.tsx b/packages/components/src/CategoryVerticalList/CategoryVerticalList.tsx index 7ea05900ac..3e6b726cbc 100644 --- a/packages/components/src/CategoryVerticalList/CategoryVerticalList.tsx +++ b/packages/components/src/CategoryVerticalList/CategoryVerticalList.tsx @@ -4,13 +4,13 @@ import { CardButton } from '../CardButton/CardButton' import { getGlyph, Icon } from '../Icon/Icon' import { VerticalList } from '../VerticalList/VerticalList.client' -import type { DBCategory, ICategory } from 'oa-shared' +import type { Category, ICategory } from 'oa-shared' import type { availableGlyphs } from '../Icon/types' export interface IProps { - activeCategory: DBCategory | ICategory | null - allCategories: (DBCategory | ICategory)[] - setActiveCategory: (category: DBCategory | ICategory | null) => void + activeCategory: Category | ICategory | null + allCategories: (Category | ICategory)[] + setActiveCategory: (category: Category | ICategory | null) => void } export const CategoryVerticalList = (props: IProps) => { @@ -21,8 +21,8 @@ export const CategoryVerticalList = (props: IProps) => { } const orderedCategories = allCategories.toSorted((a, b) => - (a as DBCategory).created_at - ? (a as DBCategory).created_at > (b as DBCategory).created_at + (a as Category).createdAt + ? (a as Category).createdAt > (b as Category).createdAt ? 1 : -1 : (a as ICategory)._created > (b as ICategory)._created @@ -30,9 +30,9 @@ export const CategoryVerticalList = (props: IProps) => { : -1, ) - const isCategorySelected = (category: DBCategory | ICategory) => { - if ((category as DBCategory).id) { - return (category as DBCategory).id === (activeCategory as DBCategory)?.id + const isCategorySelected = (category: Category | ICategory) => { + if ((category as Category).id) { + return (category as Category).id === (activeCategory as Category)?.id } if ((category as ICategory)._id) { return (category as ICategory)._id === (activeCategory as ICategory)?._id @@ -44,7 +44,7 @@ export const CategoryVerticalList = (props: IProps) => { {orderedCategories.map((category, index) => { const isSelected = isCategorySelected(category) const name = - (category as DBCategory).name || (category as ICategory).label + (category as Category).name || (category as ICategory).label const glyph = name.toLowerCase() as availableGlyphs const hasGlyph = getGlyph(glyph) diff --git a/packages/components/src/ProfileTagsList/ProfileTagsList.tsx b/packages/components/src/ProfileTagsList/ProfileTagsList.tsx index c7f2fb8551..313f87cb8c 100644 --- a/packages/components/src/ProfileTagsList/ProfileTagsList.tsx +++ b/packages/components/src/ProfileTagsList/ProfileTagsList.tsx @@ -2,7 +2,7 @@ import { Flex } from 'theme-ui' import { Category } from '../Category/Category' -import type { DBCategory, IProfileTag } from 'oa-shared' +import type { Category as CategoryType, IProfileTag } from 'oa-shared' import type { ThemeUIStyleObject } from 'theme-ui' export interface IProps { @@ -20,7 +20,7 @@ export const ProfileTagsList = ({ sx, tags }: IProps) => { label && ( { - const [categories, setCategories] = useState([]) + const [categories, setCategories] = useState([]) const [searchString, setSearchString] = useState('') const [searchParams, setSearchParams] = useSearchParams() @@ -95,7 +95,7 @@ export const QuestionListHeader = () => { setActiveCategory={(updatedCategory) => updateFilter( QuestionSearchParams.category, - updatedCategory ? (updatedCategory as DBCategory).id.toString() : '', + updatedCategory ? (updatedCategory as Category).id.toString() : '', ) } /> diff --git a/src/pages/Question/QuestionPage.test.tsx b/src/pages/Question/QuestionPage.test.tsx index eda0d0946f..d983a687c1 100644 --- a/src/pages/Question/QuestionPage.test.tsx +++ b/src/pages/Question/QuestionPage.test.tsx @@ -67,7 +67,7 @@ describe('Questions', () => { mockQuestionItem.title = 'Do you prefer camping near a lake or in a forest?' mockQuestionItem.category = { - created_at: new Date(), + createdAt: new Date(), name: 'Preference', id: faker.number.int(), type: 'questions', diff --git a/src/pages/Question/question.service.ts b/src/pages/Question/question.service.ts index ca2796be83..522f91fd41 100644 --- a/src/pages/Question/question.service.ts +++ b/src/pages/Question/question.service.ts @@ -1,6 +1,6 @@ import { logger } from 'src/logger' -import type { DBCategory } from 'oa-shared' +import type { Category } from 'oa-shared' import type { Question } from 'src/models/question.model' import type { QuestionSortOption } from './QuestionSortOptions' @@ -40,7 +40,7 @@ const search = async ( const getQuestionCategories = async () => { try { const response = await fetch('/api/categories/questions') - return (await response.json()) as DBCategory[] + return (await response.json()) as Category[] } catch (error) { logger.error('Failed to fetch questions', { error }) return [] diff --git a/src/routes/api.categories.$type.ts b/src/routes/api.categories.$type.ts index 3ea45dd2db..d6e66cbac8 100644 --- a/src/routes/api.categories.$type.ts +++ b/src/routes/api.categories.$type.ts @@ -1,13 +1,14 @@ import Keyv from 'keyv' +import { Category } from 'oa-shared' import { isProductionEnvironment } from 'src/config/config' import { createSupabaseServerClient } from 'src/repository/supabase.server' import type { LoaderFunctionArgs } from '@remix-run/node' import type { ContentTypes, DBCategory } from 'oa-shared' -const cache = new Keyv({ ttl: 3600000 }) // ttl: 60 minutes +const cache = new Keyv({ ttl: 3600000 }) // ttl: 60 minutes -const filterByType = (categories: DBCategory[], type: ContentTypes) => { +const filterByType = (categories: Category[], type: ContentTypes) => { return categories.filter((category) => category.type === type) } @@ -35,11 +36,18 @@ export async function loader({ request, params }: LoaderFunctionArgs) { .from('categories') .select('id,name,created_at,type') - if (data && data.length > 0) { + const categories = data?.map((category) => + Category.fromDB(category as DBCategory), + ) + + if (categories && categories.length > 0) { cache.set('categories', data, 3600000) } - const categories = filterByType(data as DBCategory[], type) || [] + const categoriesForType = categories ? filterByType(categories, type) : [] - return Response.json(categories, { headers, status: 200 }) + return Response.json( + { categories: categoriesForType }, + { headers, status: 200 }, + ) } diff --git a/src/test/factories/Category.ts b/src/test/factories/Category.ts index a95214874d..43c83977f7 100644 --- a/src/test/factories/Category.ts +++ b/src/test/factories/Category.ts @@ -1,7 +1,7 @@ -import type { DBCategory } from 'oa-shared' +import type { Category } from 'oa-shared' -export const FactoryCategory: DBCategory = { - created_at: new Date('2018-11-29T12:56:47.901Z'), +export const FactoryCategory: Category = { + createdAt: new Date('2018-11-29T12:56:47.901Z'), id: 3465, name: 'Moulds', type: 'questions', diff --git a/src/test/factories/Question.ts b/src/test/factories/Question.ts index 0fcd5bab72..bdf422e388 100644 --- a/src/test/factories/Question.ts +++ b/src/test/factories/Question.ts @@ -32,7 +32,7 @@ export const FactoryQuestionItem = ( username: faker.internet.userName(), }, category: { - created_at: new Date(), + createdAt: new Date(), id: faker.number.int(), name: faker.lorem.words(1), type: 'questions',