diff --git a/apps/web/src/app/settings/page.tsx b/apps/web/src/app/settings/page.tsx index 29e8256..e980b49 100644 --- a/apps/web/src/app/settings/page.tsx +++ b/apps/web/src/app/settings/page.tsx @@ -1,11 +1,12 @@ import { Settings } from "@/components/settings"; +import { Suspense } from "react"; export default function SettingsPage() { // let's keep this page here for SSR, possibly to prefech some data on the server side, suspense queries etc. return ( - <> + - + ); } diff --git a/apps/web/src/components/CompaniesList.tsx b/apps/web/src/components/CompaniesList.tsx index ea4f5d2..1a2b6c1 100644 --- a/apps/web/src/components/CompaniesList.tsx +++ b/apps/web/src/components/CompaniesList.tsx @@ -9,7 +9,7 @@ import CompaniesListFooter from "./CompaniesListFooter"; import { CompaniesListHeader } from "./CompaniesListHeader"; import CompanyItem from "./CompanyItem"; import { EmptyState } from "./EmptyState"; -import SponsorSideSection from "./SponsorSideSection"; +import { NotificationsSideSection } from "./NotificationsSideSection"; const PAGE_SIZE = 15; @@ -89,7 +89,7 @@ export default function CompaniesList({ )}
- +
); diff --git a/apps/web/src/components/NotificationsSideSection.tsx b/apps/web/src/components/NotificationsSideSection.tsx new file mode 100644 index 0000000..1f2d7b4 --- /dev/null +++ b/apps/web/src/components/NotificationsSideSection.tsx @@ -0,0 +1,27 @@ +import { SettingsTab } from "@/lib/search-params"; +import Link from "next/link"; +import { Button } from "./ui/button"; +import { RetroContainer } from "./ui/retro-container"; + +export const NotificationsSideSection = () => { + return ( + +
+
+

Stay updated 🔔

+

+ Get notified when new companies are added. +

+
+ +
+
+ ); +}; diff --git a/apps/web/src/components/SideBar.tsx b/apps/web/src/components/SideBar.tsx index 22d4858..ca35702 100644 --- a/apps/web/src/components/SideBar.tsx +++ b/apps/web/src/components/SideBar.tsx @@ -1,5 +1,5 @@ +import { NotificationsSideSection } from "./NotificationsSideSection"; import { SearchSideBar } from "./SearchSideBar"; -import SponsorSideSection from "./SponsorSideSection"; type SideBarProps = { locationOptions: string[]; @@ -9,8 +9,7 @@ type SideBarProps = { export function SideBar({ locationOptions, categoryOptions }: SideBarProps) { return ( ); diff --git a/apps/web/src/components/SponsorSideSection.tsx b/apps/web/src/components/SponsorSideSection.tsx deleted file mode 100644 index 020852f..0000000 --- a/apps/web/src/components/SponsorSideSection.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { RetroContainer } from "./ui/retro-container"; - -export default function SponsorSideSection() { - return ( - -
-

- Be a Sponsor 💛 -

-

- - Contact us - {" "} - to become a sponsor or advertiser. -

-
-
- ); -} diff --git a/apps/web/src/components/settings/index.tsx b/apps/web/src/components/settings/index.tsx index 1ae3a08..13e7cf8 100644 --- a/apps/web/src/components/settings/index.tsx +++ b/apps/web/src/components/settings/index.tsx @@ -1,32 +1,41 @@ "use client"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import type { SettingsTab } from "@/lib/types"; +import { SettingsTab, settingsQueryStateKeys } from "@/lib/search-params"; +import type { SettingsTabs } from "@/lib/types"; import { cn } from "@/lib/utils"; -import { trackEvent } from "@tech-companies-portugal/analytics/client"; +import { useQueryStates } from "nuqs"; import { Title } from "../Title"; import { AccountSettings } from "./account/AccountSettings"; import { NotificationSettings } from "./notification/NotificationSettings"; -const TABS: SettingsTab[] = [ +const TABS: SettingsTabs[] = [ { - id: "account", + id: SettingsTab.ACCOUNT, title: "Account", }, { - id: "notifications", + id: SettingsTab.NOTIFICATIONS, title: "Notifications", }, ]; export const Settings = () => { + const [settingsTab, setSettingsTab] = useQueryStates(settingsQueryStateKeys, { + scroll: true, + }); + return (
</div> - <Tabs defaultValue="account" className="bold"> + <Tabs + value={settingsTab.tab} + onValueChange={(value) => setSettingsTab({ tab: value as SettingsTab })} + className="bold" + > <TabsList className="bg-transparent flex justify-start gap-4 w-full mb-4 overflow-x-auto scrollbar-hide"> {TABS.map((tab) => ( <TabsTrigger @@ -38,18 +47,13 @@ export const Settings = () => { )} > {tab.title} - {tab.badge && tab.badge} </TabsTrigger> ))} </TabsList> - <TabsContent value="account" className="p-0.5"> + <TabsContent value={SettingsTab.ACCOUNT} className="p-0.5"> <AccountSettings /> </TabsContent> - <TabsContent - value="notifications" - className="p-0.5" - onClick={() => trackEvent("notifications_tab_clicked")} - > + <TabsContent value={SettingsTab.NOTIFICATIONS} className="p-0.5"> <NotificationSettings /> </TabsContent> </Tabs> diff --git a/apps/web/src/components/settings/notification/NotificationSettings.tsx b/apps/web/src/components/settings/notification/NotificationSettings.tsx index 978668d..092a34c 100644 --- a/apps/web/src/components/settings/notification/NotificationSettings.tsx +++ b/apps/web/src/components/settings/notification/NotificationSettings.tsx @@ -12,7 +12,7 @@ import { memo, useCallback } from "react"; import { useThrottledCallback } from "use-debounce"; const NOTIFICATION_LABEL_MAP = { - new_companies: "Receive weekly email updates for new companies added", + new_companies: "Receive email updates for new companies added", } as const; export const NotificationSettings = () => { diff --git a/apps/web/src/lib/search-params.ts b/apps/web/src/lib/search-params.ts index 4b967a2..bb203e1 100644 --- a/apps/web/src/lib/search-params.ts +++ b/apps/web/src/lib/search-params.ts @@ -3,6 +3,7 @@ import { createSearchParamsCache, parseAsFloat, parseAsString, + parseAsStringEnum, } from "nuqs/server"; export const defaultSearchParams = { @@ -12,6 +13,15 @@ export const defaultSearchParams = { page: 1, }; +export enum SettingsTab { + ACCOUNT = "account", + NOTIFICATIONS = "notifications", +} + +export const defaultSettings = { + tab: SettingsTab.ACCOUNT, +}; + // can be used in the client as well export const searchParamsQueryStateKeys = { query: parseAsString.withDefault(defaultSearchParams.query), @@ -27,3 +37,16 @@ export const loadSearchParams = createLoader(searchParamsQueryStateKeys); export const searchParamsCache = createSearchParamsCache( searchParamsQueryStateKeys, ); + +// query state keys for the settings page +export const settingsQueryStateKeys = { + tab: parseAsStringEnum<SettingsTab>(Object.values(SettingsTab)).withDefault( + defaultSettings.tab, + ), +}; + +// for server side +export const loadSettings = createLoader(settingsQueryStateKeys); + +// For getting server side cached settings in nested components tree +export const settingsCache = createSearchParamsCache(settingsQueryStateKeys); diff --git a/apps/web/src/lib/types.ts b/apps/web/src/lib/types.ts index 3f6a019..880a207 100644 --- a/apps/web/src/lib/types.ts +++ b/apps/web/src/lib/types.ts @@ -1,3 +1,5 @@ +import type { SettingsTab } from "./search-params"; + export type Company = { slug: string; name: string; @@ -27,8 +29,8 @@ export type PageViewsData = { export type NextParams<T> = Promise<T>; -export type SettingsTab = { - id: string; +export type SettingsTabs = { + id: SettingsTab; title: string; disabled?: boolean; badge?: React.ReactNode;