Automatic data reload, scroll restoration and missing drink pages
This commit is contained in:
+3
-1
@@ -6,7 +6,8 @@ import {
|
||||
useRouteError,
|
||||
isRouteErrorResponse,
|
||||
json,
|
||||
useLoaderData
|
||||
useLoaderData,
|
||||
ScrollRestoration
|
||||
} from "@remix-run/react";
|
||||
import type { PropsWithChildren } from "react";
|
||||
|
||||
@@ -37,6 +38,7 @@ function Document({
|
||||
</head>
|
||||
<body>
|
||||
{children}
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import type {
|
||||
LoaderFunctionArgs
|
||||
} from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import {
|
||||
useLoaderData,
|
||||
useParams,
|
||||
isRouteErrorResponse,
|
||||
useRouteError } from "@remix-run/react";
|
||||
|
||||
import DrinkPage from "~/components/cards/drink.page";
|
||||
|
||||
import { db } from "~/utils/db.server";
|
||||
import { enhance } from "@zenstackhq/runtime";
|
||||
import { findIdFromSlug } from "~/models/drinks.server";
|
||||
|
||||
export const loader = async ({
|
||||
params,
|
||||
}: LoaderFunctionArgs) => {
|
||||
const dbe = enhance(db);
|
||||
|
||||
const cocktailid = await findIdFromSlug(params.cocktailslug);
|
||||
|
||||
const cocktail = await dbe.cocktail.findUnique({
|
||||
where: { id: cocktailid },
|
||||
include: { manufacturer: true, containers: { include: { section: true}}}
|
||||
});
|
||||
if (!cocktail) {
|
||||
throw new Response("Cocktail not found.", {
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
return json({ cocktail });
|
||||
};
|
||||
|
||||
export default function CocktailRoute() {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<DrinkPage drink={data.cocktail}></DrinkPage>
|
||||
);
|
||||
}
|
||||
|
||||
export function ErrorBoundary() {
|
||||
const { cocktailid } = useParams();
|
||||
const error = useRouteError();
|
||||
|
||||
if (isRouteErrorResponse(error)) {
|
||||
if (error.status === 400) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
What you're trying to do is not allowed.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (error.status === 404) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
Huh? What the heck is "{cocktailid}"?
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="error-container">
|
||||
There was an error loading cocktail by the id "{cocktailid}".
|
||||
Sorry.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { Outlet, json, useLoaderData } from "@remix-run/react";
|
||||
import { Outlet, json, useLoaderData, useRevalidator } from "@remix-run/react";
|
||||
import { useEffect } from "react";
|
||||
import { getSession } from "~/auth/session";
|
||||
import Header, { HeaderData } from "~/components/header";
|
||||
|
||||
@@ -20,8 +21,21 @@ export async function loader({
|
||||
return json({data});
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default function InventoryLayout() {
|
||||
let data = useLoaderData<typeof loader>();
|
||||
let revalidator = useRevalidator();
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
if (revalidator.state === "idle") {
|
||||
revalidator.revalidate();
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -31,9 +31,7 @@ export default function BeersRoute() {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
function CustomToggle({ children, eventKey } : any) {
|
||||
const decoratedOnClick = useAccordionButton(eventKey, () =>
|
||||
console.log('totally custom!'),
|
||||
);
|
||||
const decoratedOnClick = useAccordionButton(eventKey, () => {});
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
||||
@@ -1,73 +1,71 @@
|
||||
import type {
|
||||
LoaderFunctionArgs
|
||||
LoaderFunctionArgs
|
||||
} from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import {
|
||||
useLoaderData,
|
||||
useParams,
|
||||
isRouteErrorResponse,
|
||||
useRouteError } from "@remix-run/react";
|
||||
|
||||
import DrinkCard from "~/components/cards/drink.card";
|
||||
useLoaderData,
|
||||
useParams,
|
||||
isRouteErrorResponse,
|
||||
useRouteError } from "@remix-run/react";
|
||||
|
||||
import DrinkPage from "~/components/cards/drink.page";
|
||||
|
||||
import { db } from "~/utils/db.server";
|
||||
import { enhance } from "@zenstackhq/runtime";
|
||||
import { findIdFromSlug } from "~/models/drinks.server";
|
||||
|
||||
export const loader = async ({
|
||||
params,
|
||||
params,
|
||||
}: LoaderFunctionArgs) => {
|
||||
const dbe = enhance(db);
|
||||
const dbe = enhance(db);
|
||||
|
||||
const sodaid = await findIdFromSlug(params.sodaslug);
|
||||
const sodaid = await findIdFromSlug(params.sodaslug);
|
||||
|
||||
const soda = await dbe.soda.findUnique({
|
||||
include: { manufacturer: true, containers: true},
|
||||
where: { id: sodaid }
|
||||
const soda = await dbe.soda.findUnique({
|
||||
where: { id: sodaid },
|
||||
include: { manufacturer: true, containers: { include: { section: true}}}
|
||||
});
|
||||
if (!soda) {
|
||||
throw new Response("Soda not found.", {
|
||||
status: 404,
|
||||
});
|
||||
if (!soda) {
|
||||
throw new Response("Soda not found.", {
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
return json({ soda });
|
||||
}
|
||||
return json({ soda });
|
||||
};
|
||||
|
||||
export default function SodaRoute() {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DrinkCard drink={data.soda}></DrinkCard>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<DrinkPage drink={data.soda}></DrinkPage>
|
||||
);
|
||||
}
|
||||
|
||||
export function ErrorBoundary() {
|
||||
const { sodaid } = useParams();
|
||||
const error = useRouteError();
|
||||
const { sodaid } = useParams();
|
||||
const error = useRouteError();
|
||||
|
||||
if (isRouteErrorResponse(error)) {
|
||||
if (error.status === 400) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
What you're trying to do is not allowed.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (error.status === 404) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
Huh? What the heck is "{sodaid}"?
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (isRouteErrorResponse(error)) {
|
||||
if (error.status === 400) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
What you're trying to do is not allowed.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (error.status === 404) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
Huh? What the heck is "{sodaid}"?
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="error-container">
|
||||
There was an error loading soda by the id "{sodaid}".
|
||||
Sorry.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="error-container">
|
||||
There was an error loading soda by the id "{sodaid}".
|
||||
Sorry.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,73 +1,71 @@
|
||||
import type {
|
||||
LoaderFunctionArgs
|
||||
LoaderFunctionArgs
|
||||
} from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import {
|
||||
useLoaderData,
|
||||
useParams,
|
||||
isRouteErrorResponse,
|
||||
useRouteError } from "@remix-run/react";
|
||||
|
||||
import DrinkCard from "~/components/cards/drink.card";
|
||||
useLoaderData,
|
||||
useParams,
|
||||
isRouteErrorResponse,
|
||||
useRouteError } from "@remix-run/react";
|
||||
|
||||
import DrinkPage from "~/components/cards/drink.page";
|
||||
|
||||
import { db } from "~/utils/db.server";
|
||||
import { enhance } from "@zenstackhq/runtime";
|
||||
import { findIdFromSlug } from "~/models/drinks.server";
|
||||
|
||||
export const loader = async ({
|
||||
params,
|
||||
params,
|
||||
}: LoaderFunctionArgs) => {
|
||||
const dbe = enhance(db);
|
||||
const dbe = enhance(db);
|
||||
|
||||
const wineid = await findIdFromSlug(params.wineslug);
|
||||
const wineid = await findIdFromSlug(params.wineslug);
|
||||
|
||||
const wine = await dbe.wine.findUnique({
|
||||
include: { style: true, manufacturer: true, containers: true},
|
||||
where: { id: wineid },
|
||||
const wine = await dbe.wine.findUnique({
|
||||
where: { id: wineid },
|
||||
include: { style: true, manufacturer: true, containers: { include: { section: true}}}
|
||||
});
|
||||
if (!wine) {
|
||||
throw new Response("Wine not found.", {
|
||||
status: 404,
|
||||
});
|
||||
if (!wine) {
|
||||
throw new Response("Wine not found.", {
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
return json({ wine });
|
||||
}
|
||||
return json({ wine });
|
||||
};
|
||||
|
||||
export default function WineRoute() {
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DrinkCard drink={data.wine}></DrinkCard>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<DrinkPage drink={data.wine}></DrinkPage>
|
||||
);
|
||||
}
|
||||
|
||||
export function ErrorBoundary() {
|
||||
const { wineid } = useParams();
|
||||
const error = useRouteError();
|
||||
const { wineid } = useParams();
|
||||
const error = useRouteError();
|
||||
|
||||
if (isRouteErrorResponse(error)) {
|
||||
if (error.status === 400) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
What you're trying to do is not allowed.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (error.status === 404) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
Huh? What the heck is "{wineid}"?
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (isRouteErrorResponse(error)) {
|
||||
if (error.status === 400) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
What you're trying to do is not allowed.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (error.status === 404) {
|
||||
return (
|
||||
<div className="error-container">
|
||||
Huh? What the heck is "{wineid}"?
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="error-container">
|
||||
There was an error loading wine by the id "{wineid}".
|
||||
Sorry.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="error-container">
|
||||
There was an error loading wine by the id "{wineid}".
|
||||
Sorry.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { LoaderFunctionArgs, redirect, json } from "@remix-run/node";
|
||||
import { enhance } from "~/utils/db.server";
|
||||
|
||||
export async function loader({
|
||||
request,
|
||||
}: LoaderFunctionArgs) {
|
||||
const { dbe } = await enhance(request);
|
||||
|
||||
const numCheckouts = await dbe.history.count({});
|
||||
return json({checkouts: numCheckouts});
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { Outlet, json, redirect, useLoaderData } from "@remix-run/react";
|
||||
import { Outlet, json, redirect, useLoaderData, useRevalidator } from "@remix-run/react";
|
||||
import { useEffect } from "react";
|
||||
import { enhance } from "~/utils/db.server";
|
||||
|
||||
export async function loader({
|
||||
@@ -17,6 +18,18 @@ export async function loader({
|
||||
export default function InventoryLayout() {
|
||||
useLoaderData<typeof loader>();
|
||||
|
||||
let revalidator = useRevalidator();
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
if (revalidator.state === "idle") {
|
||||
revalidator.revalidate();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
|
||||
Generated
+13
@@ -10,6 +10,7 @@
|
||||
"@remix-run/node": "^2.9.1",
|
||||
"@remix-run/react": "^2.9.1",
|
||||
"@remix-run/serve": "^2.9.1",
|
||||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"@zenstackhq/runtime": "2.0.3",
|
||||
"bootstrap": "^5.3.3",
|
||||
"isbot": "^4.1.0",
|
||||
@@ -2692,6 +2693,18 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@uidotdev/usehooks": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz",
|
||||
"integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ungap/structured-clone": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"@remix-run/node": "^2.9.1",
|
||||
"@remix-run/react": "^2.9.1",
|
||||
"@remix-run/serve": "^2.9.1",
|
||||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"@zenstackhq/runtime": "2.0.3",
|
||||
"bootstrap": "^5.3.3",
|
||||
"isbot": "^4.1.0",
|
||||
|
||||
@@ -12,12 +12,16 @@ export default defineConfig({
|
||||
// Index
|
||||
route("/", "routes/_index.tsx", { index: true });
|
||||
|
||||
// Resources
|
||||
route("/resource/checkouts", "routes/resource/checkouts.tsx");
|
||||
|
||||
// Inventory
|
||||
route("inventory", "routes/inventory/layout.tsx", () => {
|
||||
route("", "routes/inventory/route.tsx", { index: true });
|
||||
route("beer/:beerslug", "routes/inventory/beer.$beerslug.tsx");
|
||||
route("wine/:wineslug", "routes/inventory/wine.$wineslug.tsx");
|
||||
route("soda/:sodaslug", "routes/inventory/soda.$sodaslug.tsx");
|
||||
route("cocktail/:cocktailslug", "routes/inventory/cocktail.$cocktailslug.tsx");
|
||||
|
||||
route("stats", "routes/inventory/stats/route.tsx");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user