diff --git a/src/components/mii/list/index.tsx b/src/components/mii/list/index.tsx index 33042eb..081712e 100644 --- a/src/components/mii/list/index.tsx +++ b/src/components/mii/list/index.tsx @@ -5,6 +5,7 @@ import { auth } from "@/lib/auth"; import { prisma } from "@/lib/prisma"; import SortSelect from "./sort-select"; +import TimeRangeSelect from "./time-range-select"; import Pagination from "./pagination"; import FilterMenu from "./filter-menu"; import MiiGrid from "./mii-grid"; @@ -20,7 +21,7 @@ export default async function MiiList({ searchParams, userId, parentPage }: Prop const parsed = searchSchema.safeParse(searchParams); if (!parsed.success) return

{parsed.error.issues[0].message}

; - const { q: query, sort, tags, exclude, platform, gender, makeup, allowCopying, quarantined, page = 1, limit = 24 } = parsed.data; + const { q: query, sort, tags, exclude, platform, gender, makeup, allowCopying, quarantined, page = 1, limit = 24, timeRange } = parsed.data; // My Likes page let miiIdsLiked: number[] | undefined = undefined; @@ -66,6 +67,14 @@ export default async function MiiList({ searchParams, userId, parentPage }: Prop ...(makeup && { makeup: { equals: makeup } }), // Quarantined ...(!quarantined && !userId && { quarantined: false }), + // Time range + ...(timeRange && { + createdAt: { + gte: new Date( + Date.now() - { day: 86400000, week: 604800000, month: 2592000000, year: 31536000000 }[timeRange], + ), + }, + }), }; const select: Prisma.MiiSelect = { @@ -143,6 +152,7 @@ export default async function MiiList({ searchParams, userId, parentPage }: Prop
+
diff --git a/src/components/mii/list/time-range-select.tsx b/src/components/mii/list/time-range-select.tsx new file mode 100644 index 0000000..48880ec --- /dev/null +++ b/src/components/mii/list/time-range-select.tsx @@ -0,0 +1,71 @@ +"use client"; + +import { useRouter, useSearchParams } from "next/navigation"; +import { useTransition } from "react"; +import { useSelect } from "downshift"; +import { Icon } from "@iconify/react"; + +type TimeRange = "day" | "week" | "month" | "year"; + +const items: { value: TimeRange | "all"; label: string }[] = [ + { value: "all", label: "all time" }, + { value: "day", label: "today" }, + { value: "week", label: "this week" }, + { value: "month", label: "this month" }, + { value: "year", label: "this year" }, +]; + +export default function TimeRangeSelect() { + const router = useRouter(); + const searchParams = useSearchParams(); + const [, startTransition] = useTransition(); + + const currentRange = (searchParams.get("timeRange") as TimeRange) || "all"; + const currentItem = items.find((i) => i.value === currentRange) || items[0]; + + const { isOpen, getToggleButtonProps, getMenuProps, getItemProps, highlightedIndex, selectedItem } = useSelect({ + items, + selectedItem: currentItem, + itemToString: (item) => item?.label || "", + onSelectedItemChange: ({ selectedItem }) => { + if (!selectedItem) return; + + const params = new URLSearchParams(searchParams); + params.set("page", "1"); + + if (selectedItem.value === "all") { + params.delete("timeRange"); + } else { + params.set("timeRange", selectedItem.value); + } + + startTransition(() => { + router.push(`?${params.toString()}`, { scroll: false }); + }); + }, + }); + + return ( +
+ + + +
+ ); +} diff --git a/src/lib/schemas.ts b/src/lib/schemas.ts index 490cc5f..94318e7 100644 --- a/src/lib/schemas.ts +++ b/src/lib/schemas.ts @@ -72,6 +72,8 @@ export const searchSchema = z.object({ .max(100, { error: "Limit cannot be more than 100" }) .optional(), page: z.coerce.number({ error: "Page must be a number" }).int({ error: "Page must be an integer" }).min(1, { error: "Page must be at least 1" }).optional(), + // Time range filter + timeRange: z.enum(["day", "week", "month", "year"], { error: "Time range must be either 'day', 'week', 'month', or 'year'" }).optional(), }); export const userNameSchema = z