Skip to content

Commit

Permalink
add hero context (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
dogfrogfog authored Jul 10, 2024
1 parent 917dadf commit 49a05a5
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 29 deletions.
6 changes: 5 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Metadata } from "next";
import RootLayoutComponent from "@/components/layouts/RootLayout";
import { FeatureMono } from "../fonts";
import HeroContextLayout from "@/components/layouts/HeroContextLayout";

import "./globals.css";

export const metadata: Metadata = {
Expand All @@ -16,7 +18,9 @@ export default function RootLayout({
return (
<html lang="en">
<body className={FeatureMono.className}>
<RootLayoutComponent>{children}</RootLayoutComponent>
<HeroContextLayout>
<RootLayoutComponent>{children}</RootLayoutComponent>
</HeroContextLayout>
</body>
</html>
);
Expand Down
43 changes: 43 additions & 0 deletions src/components/contexts/HeroContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import {
createContext,
Dispatch,
ReactNode,
SetStateAction,
useContext,
useState,
} from "react";
import type { GetHeroResponse } from "@/api/proto-http/frontend";

const HeroContext = createContext<
GetHeroResponse & {
selectedCurrency: string;
setSelectedCurrency: Dispatch<SetStateAction<string>>;
}
>({
hero: undefined,
dictionary: undefined,
rates: undefined,
selectedCurrency: "",
setSelectedCurrency: () => {},
});

export function HeroContextProvider({
children,
...props
}: GetHeroResponse & { children: ReactNode }) {
const [selectedCurrency, setSelectedCurrency] = useState(
props.dictionary?.baseCurrency || "",
);

return (
<HeroContext.Provider
value={{ ...props, selectedCurrency, setSelectedCurrency }}
>
{children}
</HeroContext.Provider>
);
}

export const useHeroContext = () => useContext(HeroContext);
38 changes: 38 additions & 0 deletions src/components/global/Footer/CurrencyPopover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"use client";

import { useHeroContext } from "@/components/contexts/HeroContext";
import GenericPopover from "@/components/ui/Popover";
import { cn } from "@/lib/utils";

export default function Component() {
const { rates, selectedCurrency, setSelectedCurrency } = useHeroContext();

if (!rates?.currencies) return null;

return (
<GenericPopover
title="currency"
openElement={
<span className="bg-textColor px-2 py-1 text-buttonTextColor">
{`Currency: ${selectedCurrency}`}
</span>
}
>
<div className="space-y-2 px-12 pb-7">
{Object.entries(rates.currencies).map(([k, v]) => (
<button
key={k}
onClick={() => {
setSelectedCurrency(k);
}}
className={cn("flex items-center gap-1 text-sm", {
underline: k === selectedCurrency,
})}
>
{v.description} {JSON.stringify(v.rate)}
</button>
))}
</div>
</GenericPopover>
);
}
30 changes: 5 additions & 25 deletions src/components/global/Footer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Link from "next/link";
import { FOOTER_LINKS as links, FOOTER_YEAR as year } from "@/constants";
import { serviceClient } from "@/lib/api";
import { cn } from "@/lib/utils";
import Link from "next/link";
import FooterForm from "../../forms/NewslatterForm";
import GenericPopover from "@/components/ui/Popover";
import Button from "@/components/ui/Button";
import FooterForm from "../../forms/NewslatterForm";
import CurrencyPopover from "./CurrencyPopover";

// todo: sync with BE
const currencyNameMap = {
Expand Down Expand Up @@ -32,6 +32,7 @@ export default function Footer({
}) {
async function formSubmitClick(data: FormData): Promise<void> {
"use server";

try {
const payload: { email: string; name: string } = {
email: data.get("email") as string,
Expand Down Expand Up @@ -72,28 +73,7 @@ export default function Footer({
<Link href="privacy-policy">privacy policy</Link>
</Button>
</div>
<div>
<GenericPopover
title="currency"
openElement={
<span className="bg-textColor px-2 py-1 text-buttonTextColor">
{`Currency: ${currentCurrency}`}
</span>
}
>
<div className="space-y-2 px-12 pb-7">
{Object.entries(currencyNameMap).map(([k, v]) => (
<button
key={k + v}
className="flex items-center gap-1 text-sm first:underline"
>
<span>{k}</span>
<span>{v}</span>
</button>
))}
</div>
</GenericPopover>
</div>
<CurrencyPopover />
</div>
</div>
</footer>
Expand Down
12 changes: 12 additions & 0 deletions src/components/layouts/HeroContextLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { serviceClient } from "@/lib/api";
import { HeroContextProvider } from "../contexts/HeroContext";

type Props = {
children: React.ReactNode;
};

export default async function Layout({ children }: Props) {
const heroData = await serviceClient.GetHero({});

return <HeroContextProvider {...heroData}>{children}</HeroContextProvider>;
}
4 changes: 1 addition & 3 deletions src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ interface ProtoMetaParams {

const fetchParams: Object = {
GetHero: {
next: {
revalidate: 15,
},
cache: "no-store",
},
GetProduct: {
next: {
Expand Down

0 comments on commit 49a05a5

Please sign in to comment.