Skip to content

Commit

Permalink
wip: questionsPage (/xyz) refactor within /abc route, context test, b…
Browse files Browse the repository at this point in the history
…rowserTab title test
  • Loading branch information
mewdev committed Jan 9, 2025
1 parent 5a180e2 commit d82d4b1
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 0 deletions.
22 changes: 22 additions & 0 deletions apps/web/app/abc/components/counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use client";

import { useCounterStore } from "../providers/counterStoreProvider";

export default function Counter() {
const { count, incrementCount, decrementCount } = useCounterStore(
(state) => state,
);

return (
<div>
Count: {count}
<hr />
<button type="button" onClick={() => void incrementCount()}>
Increment Count
</button>
<button type="button" onClick={() => void decrementCount()}>
Decrement Count
</button>
</div>
);
}
11 changes: 11 additions & 0 deletions apps/web/app/abc/counter/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";

import Counter from "../components/counter";

export default function Page() {
return (
<div>
<Counter />
</div>
);
}
21 changes: 21 additions & 0 deletions apps/web/app/abc/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import "../globals.css";
import "@repo/design-system/styles";
import "@repo/design-system/themes/theme-default";
import { CounterStoreProvider } from "./providers/counterStoreProvider";
import UrlUpdater from "./utils/urlUpdater";

export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<CounterStoreProvider>
<UrlUpdater>
<body>{children}</body>
</UrlUpdater>
</CounterStoreProvider>
</html>
);
}
48 changes: 48 additions & 0 deletions apps/web/app/abc/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client";

import { useEffect, useState } from "react";

type Question = {
id: string;
title: string;
statement: string;
detail: string;
tags: string[];
};

export default function Page() {
const [isLoading, setIsLoading] = useState(true);
const [questions, setQuestions] = useState([]);

useEffect(() => {
// make a generic fn
async function fetchQuestions() {
const res = await fetch(
"https://www.volebnikalkulacka.cz/data/instance/volebnikalkulacka.cz/krajske-2024/10-jihomoravsky/questions.json",
);
const data = await res.json();
setQuestions(data);
setIsLoading(false);
}
fetchQuestions();
}, []);

// loading ui
if (isLoading) {
return <h1>Data is Loading</h1>;
}
// loaded ui
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div>
{questions?.map((question: Question) => {
return (
<div key={question.id} className="m-4 bg-red-400">
<span>{question.statement}</span>
</div>
);
})}
</div>
</main>
);
}
43 changes: 43 additions & 0 deletions apps/web/app/abc/providers/counterStoreProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import { type ReactNode, createContext, useRef, useContext } from "react";
import { useStore } from "zustand";

import { type CounterStore, createCounterStore } from "../store";

export type CounterStoreApi = ReturnType<typeof createCounterStore>;

export const CounterStoreContext = createContext<CounterStoreApi | undefined>(
undefined,
);

export interface CounterStoreProviderProps {
children: ReactNode;
}

export const CounterStoreProvider = ({
children,
}: CounterStoreProviderProps) => {
const storeRef = useRef<CounterStoreApi>();
if (!storeRef.current) {
storeRef.current = createCounterStore();
}

return (
<CounterStoreContext.Provider value={storeRef.current}>
{children}
</CounterStoreContext.Provider>
);
};

export const useCounterStore = <T,>(
selector: (store: CounterStore) => T,
): T => {
const counterStoreContext = useContext(CounterStoreContext);

if (!counterStoreContext) {
throw new Error(`useCounterStore must be used within CounterStoreProvider`);
}

return useStore(counterStoreContext, selector);
};
26 changes: 26 additions & 0 deletions apps/web/app/abc/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createStore } from "zustand/vanilla";

export type CounterState = {
count: number;
};

export type CounterActions = {
decrementCount: () => void;
incrementCount: () => void;
};

export type CounterStore = CounterState & CounterActions;

export const defaultInitState: CounterState = {
count: 0,
};

export const createCounterStore = (
initState: CounterState = defaultInitState,
) => {
return createStore<CounterStore>()((set) => ({
...initState,
decrementCount: () => set((state) => ({ count: state.count - 1 })),
incrementCount: () => set((state) => ({ count: state.count + 1 })),
}));
};
19 changes: 19 additions & 0 deletions apps/web/app/abc/utils/urlUpdater.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use client";
import { useEffect } from "react";
import { useCounterStore } from "../providers/counterStoreProvider";

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

export default function UrlUpdater({ children }: Props) {
const count = useCounterStore((state) => state.count);

useEffect(() => {
function changeTitle() {
document.title = `Hello World: ${count}`;
}
changeTitle();
}, [count]);
return children;
}

0 comments on commit d82d4b1

Please sign in to comment.