-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move SSR approach into common hook (#104)
* Move SSR approach into common hook Get fully typed access on the initial data * Change shape of SSR context data * Merge parent context into current one * Updates to support the cleaner SSR structure * Add SSR around plan page Add layout so data available in root page * Rework admin award export Default only * Flip sort order on award picker * Add award things to SSR
- Loading branch information
Showing
24 changed files
with
398 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,43 @@ | ||
"use client"; | ||
|
||
import { createContext } from "react"; | ||
import { type AnyProcedure, type AnyRouter } from "@trpc/server"; | ||
import { type inferTransformedProcedureOutput } from "@trpc/server/shared"; | ||
import { createContext, useContext } from "react"; | ||
|
||
import { type RouterOutputs } from "~/utils/api"; | ||
import { type appRouter } from "~/server/api/root"; | ||
|
||
export type SsrContextData = Partial<{ | ||
getPossibleSentences: RouterOutputs["questionRouter"]["getPossibleSentences"]; | ||
getSingleLearningPlan: RouterOutputs["planRouter"]["getSingleLearningPlan"]; | ||
getUserStats: RouterOutputs["questionRouter"]["getUserStats"]; | ||
}>; | ||
import { deepMerge } from "./deepMerge"; | ||
|
||
export const SsrContext = createContext<SsrContextData>({}); | ||
export type SsrQueryShape<TRouter extends AnyRouter> = { | ||
[TKey in keyof TRouter["_def"]["record"]]: TRouter["_def"]["record"][TKey] extends infer TRouterOrProcedure | ||
? TRouterOrProcedure extends AnyRouter | ||
? Partial<SsrQueryShape<TRouterOrProcedure>> | ||
: TRouterOrProcedure extends AnyProcedure | ||
? Partial<inferTransformedProcedureOutput<TRouterOrProcedure>> | ||
: never | ||
: undefined; | ||
}; | ||
|
||
type SsrDataStructure = Partial<SsrQueryShape<typeof appRouter>>; | ||
|
||
export const SsrContext = createContext<SsrDataStructure>({}); | ||
|
||
export function SsrContextProvider({ | ||
children, | ||
initialData, | ||
}: { | ||
children: React.ReactNode; | ||
initialData: SsrContextData; | ||
initialData: SsrDataStructure; | ||
}) { | ||
const parentData = useContext(SsrContext); | ||
|
||
// merge the data from the parent context with the data from the server | ||
// this allows us to nest contexts and have them all be available on the client | ||
const providerValue = deepMerge(parentData, initialData); | ||
|
||
// console.log("SsrContextProvider", { providerValue, initialData, parentData }); | ||
|
||
return ( | ||
<SsrContext.Provider value={initialData}>{children}</SsrContext.Provider> | ||
<SsrContext.Provider value={providerValue}>{children}</SsrContext.Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { callQuerySsrServer } from "~/hooks/useQuerySsrServer"; | ||
import { appRouter } from "~/server/api/root"; | ||
|
||
import { SsrContextProvider } from "../SsrContext"; | ||
import { deepMerge } from "../deepMerge"; | ||
|
||
export default async function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
const initialData = await callQuerySsrServer( | ||
appRouter.awardRouter.getAllAwardsForProfile | ||
); | ||
|
||
const moreData = await callQuerySsrServer( | ||
appRouter.awardRouter.getAllAwardImages, | ||
{ | ||
shouldLimitToProfile: true, | ||
} | ||
); | ||
|
||
const mergedData = deepMerge(initialData, moreData); | ||
|
||
return ( | ||
<SsrContextProvider initialData={mergedData}>{children}</SsrContextProvider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
type AnyObject = Record<string, any>; | ||
|
||
export function deepMerge(obj1: AnyObject, obj2: AnyObject): AnyObject { | ||
const output: AnyObject = { ...obj1 }; | ||
|
||
for (const key in obj2) { | ||
if (Object.prototype.hasOwnProperty.call(obj2, key)) { | ||
if ( | ||
typeof obj2[key] === "object" && | ||
!Array.isArray(obj2[key]) && | ||
obj2[key] !== null | ||
) { | ||
if ( | ||
typeof obj1[key] === "object" && | ||
!Array.isArray(obj1[key]) && | ||
obj1[key] !== null | ||
) { | ||
output[key] = deepMerge(obj1[key], obj2[key]); | ||
} else { | ||
output[key] = obj2[key]; | ||
} | ||
} else { | ||
output[key] = obj2[key]; | ||
} | ||
} | ||
} | ||
|
||
return output; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
"use client"; | ||
import { | ||
Card, | ||
CardContent, | ||
CardDescription, | ||
CardHeader, | ||
CardTitle, | ||
} from "~/components/ui/card"; | ||
import { useQuerySsr } from "~/hooks/useQuerySsr"; | ||
|
||
import { LearningPlanInputForm } from "./LearningPlanInputForm"; | ||
import { LearningPlanCard } from "./LearningPlanCard"; | ||
|
||
import { trpc } from "../_trpc/client"; | ||
|
||
export function PlanPageComp() { | ||
const { data: learningPlans } = useQuerySsr( | ||
trpc.planRouter.getAllLearningPlans | ||
); | ||
|
||
return ( | ||
<div> | ||
<h1>Plan</h1> | ||
|
||
<h2>All Learning Plans</h2> | ||
<div className="flex flex-wrap p-4"> | ||
{learningPlans?.map((learningPlan) => ( | ||
<LearningPlanCard key={learningPlan.id} learningPlan={learningPlan} /> | ||
))} | ||
</div> | ||
|
||
<Card className="w-96"> | ||
<CardHeader> | ||
<CardTitle>Add Learning Plan</CardTitle> | ||
<CardDescription> | ||
Use this section to create a new learning plan. You can add lessons | ||
and linked words later. | ||
</CardDescription> | ||
</CardHeader> | ||
<CardContent> | ||
<LearningPlanInputForm /> | ||
</CardContent> | ||
</Card> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.