diff --git a/src/components/RecipeList/RecipeList.test.tsx b/src/components/RecipeList/RecipeList.test.tsx index aa2ea3b..9f24975 100644 --- a/src/components/RecipeList/RecipeList.test.tsx +++ b/src/components/RecipeList/RecipeList.test.tsx @@ -37,6 +37,7 @@ describe("", () => { time: "30 min", total_time: 30, tags: ["test"], + created_at: "2024-01-01T00:00:00.000Z", })); const { getByText, queryByText } = render(() => ( @@ -60,6 +61,7 @@ describe("", () => { time: "30 min", total_time: 30, tags: ["test"], + created_at: "2024-01-01T00:00:00.000Z", })); const mockOnPageChange = vi.fn(); @@ -82,6 +84,7 @@ describe("", () => { time: "30 min", total_time: 30, tags: ["test"], + created_at: "2024-01-01T00:00:00.000Z", })); const mockOnPageChange = vi.fn(); @@ -103,6 +106,7 @@ describe("", () => { time: "30 min", total_time: 30, tags: ["test"], + created_at: "2024-01-01T00:00:00.000Z", })); render(() => ); @@ -121,6 +125,7 @@ describe("", () => { time: "30 min", total_time: 30, tags: ["test"], + created_at: "2024-01-01T00:00:00.000Z", })); const mockOnPageChange = vi.fn(); @@ -142,6 +147,7 @@ describe("", () => { time: "45 min", total_time: 45, tags: ["new"], + created_at: "2024-01-01T00:00:00.000Z", })); render(() => ( @@ -171,6 +177,7 @@ describe("", () => { time: "30 min", total_time: 30, tags: ["test"], + created_at: "2024-01-01T00:00:00.000Z", })); const mockOnPageChange = vi.fn(); diff --git a/src/components/SearchBar/SearchBar.test.tsx b/src/components/SearchBar/SearchBar.test.tsx index 1498836..5055050 100644 --- a/src/components/SearchBar/SearchBar.test.tsx +++ b/src/components/SearchBar/SearchBar.test.tsx @@ -12,6 +12,7 @@ const mockRecipes: Recipe[] = [ time: "35 min", total_time: 35, tags: ["chicken", "herbs"], + created_at: "2024-01-01T00:00:00.000Z", }, { id: "2", @@ -21,6 +22,7 @@ const mockRecipes: Recipe[] = [ time: "20 min", total_time: 20, tags: ["quinoa", "salad"], + created_at: "2024-01-02T00:00:00.000Z", }, { id: "3", @@ -30,6 +32,7 @@ const mockRecipes: Recipe[] = [ time: "15 min", total_time: 15, tags: ["chicken", "salad"], + created_at: "2024-01-03T00:00:00.000Z", }, ]; diff --git a/src/components/SortDropdown/SortDropdown.tsx b/src/components/SortDropdown/SortDropdown.tsx index d46eb16..1b55eb3 100644 --- a/src/components/SortDropdown/SortDropdown.tsx +++ b/src/components/SortDropdown/SortDropdown.tsx @@ -12,6 +12,8 @@ const SortDropdown = (props: SortDropdownProps) => { const [isOpen, setIsOpen] = createSignal(false); const sortOptions = [ + { value: "date-desc", label: strings.sort.dateDesc }, + { value: "date-asc", label: strings.sort.dateAsc }, { value: "name-asc", label: strings.sort.nameAsc }, { value: "name-desc", label: strings.sort.nameDesc }, { value: "time-asc", label: strings.sort.timeAsc }, diff --git a/src/constants/sortOptions.ts b/src/constants/sortOptions.ts index 0c812eb..9915c97 100644 --- a/src/constants/sortOptions.ts +++ b/src/constants/sortOptions.ts @@ -4,6 +4,8 @@ export type SortOption = { }; export const sortValues = [ + "date-desc", + "date-asc", "name-asc", "name-desc", "time-asc", @@ -13,3 +15,5 @@ export const sortValues = [ ] as const; export type SortValue = (typeof sortValues)[number]; + +export const DEFAULT_SORT: SortValue = "date-desc"; diff --git a/src/constants/strings.ts b/src/constants/strings.ts index e7439b3..8910f9c 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -20,6 +20,8 @@ export const strings = { }, sort: { label: "Sort by", + dateDesc: "Date (newest first)", + dateAsc: "Date (oldest first)", nameAsc: "Name (A-Z)", nameDesc: "Name (Z-A)", timeAsc: "Time (shortest first)", diff --git a/src/routes/index.tsx b/src/routes/index.tsx index b1385ce..4de5422 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -10,7 +10,7 @@ import { type DifficultyValue, difficultyValues, } from "~/constants/difficultyOptions"; -import { type SortValue, sortValues } from "~/constants/sortOptions"; +import { DEFAULT_SORT, type SortValue, sortValues } from "~/constants/sortOptions"; import { strings } from "~/constants/strings"; import { type TagFilter, type TagValue, tagValues } from "~/constants/tagOptions"; import { type TimeFilter, type TimeValue, timeValues } from "~/constants/timeOptions"; @@ -52,7 +52,7 @@ const Home = () => { const sortBy = createMemo(() => { const value = searchParams.sort as SortValue; - return sortValues.includes(value) ? value : "name-asc"; + return sortValues.includes(value) ? value : DEFAULT_SORT; }); const searchQuery = createMemo(() => searchParams.q || ""); @@ -82,6 +82,10 @@ const Home = () => { const getSortComparator = (sortBy: SortValue) => { switch (sortBy) { + case "date-desc": + return (a: Recipe, b: Recipe) => b.created_at.localeCompare(a.created_at); + case "date-asc": + return (a: Recipe, b: Recipe) => a.created_at.localeCompare(b.created_at); case "name-asc": return (a: Recipe, b: Recipe) => a.name.localeCompare(b.name); case "name-desc": @@ -101,7 +105,7 @@ const Home = () => { difficultyOrderReverse[a.difficulty] - difficultyOrderReverse[b.difficulty]; } default: - return (a: Recipe, b: Recipe) => a.name.localeCompare(b.name); + return (a: Recipe, b: Recipe) => b.created_at.localeCompare(a.created_at); } }; @@ -178,7 +182,7 @@ const Home = () => { const handleSortChange = (sort: SortValue) => { setSearchParams({ ...searchParams, - sort: sort !== "name-asc" ? sort : undefined, + sort: sort !== DEFAULT_SORT ? sort : undefined, page: undefined, }); }; diff --git a/src/types/Recipe.ts b/src/types/Recipe.ts index 9a0cf3b..833d8b4 100644 --- a/src/types/Recipe.ts +++ b/src/types/Recipe.ts @@ -23,6 +23,7 @@ export type RecipeData = { cuisine: string | null; source_url: string | null; video_url?: string; + created_at?: string; }; export type Recipe = { @@ -33,4 +34,5 @@ export type Recipe = { time: string; total_time: number; tags: ReadonlyArray; + created_at: string; }; diff --git a/src/utils/loadRecipes.ts b/src/utils/loadRecipes.ts index b8c205d..266c008 100644 --- a/src/utils/loadRecipes.ts +++ b/src/utils/loadRecipes.ts @@ -1,5 +1,7 @@ import type { Recipe, RecipeData } from "~/types/Recipe"; +const FALLBACK_CREATED_AT = "1970-01-01T00:00:00.000Z"; + const recipeModules = import.meta.glob("../../data/*.json", { eager: true, import: "default", @@ -25,6 +27,7 @@ const transformRecipeData = (data: RecipeData, filePath: string, index: number): time: data.total_time ? `${data.total_time} min` : "N/A", total_time: data.total_time || 0, tags: data.tags || [], + created_at: data.created_at || FALLBACK_CREATED_AT, }); export const loadRecipes = (): Recipe[] =>