这是indexloc提供的服务,不要输入任何密码
Skip to content

Refactor site hook #352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 29 additions & 12 deletions hosting/src/app/[site]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import "@/css/style.css";
import {useTanamSite} from "@/hooks/useTanamSite";
import "flatpickr/dist/flatpickr.min.css";
import "jsvectormap/dist/css/jsvectormap.css";
import {usePathname, useRouter} from "next/navigation";
import React, {useEffect, useState} from "react";

interface RootLayoutProps {
Expand All @@ -15,24 +14,42 @@ interface RootLayoutProps {

const RootLayout: React.FC<RootLayoutProps> = ({children}) => {
const [loading, setLoading] = useState<boolean>(true);
const router = useRouter();
const pathname = usePathname() ?? "";
const site = pathname.split("/")[1];
// TODO(Dennis): Fix cases if URL parameter is not a valid site ID
// See: https://github.com/oddbit/tanam/issues/347
const {getSite} = useTanamSite(site ?? "foo");
const [errorMessage, setError] = useState<string>("");
const {siteData, error} = useTanamSite();

useEffect(() => {
getSite().then((data) => {
document.title = data?.title ?? "Tanam";
if (siteData || error) {
setLoading(false);
});
}, [getSite, site, router]);
}

if (error) {
// TODO(Dennis): Check error type and set appropriate error message
setError(error);
}

if (siteData) {
document.title = siteData.title ?? "Tanam";
} else if (error) {
document.title = "Error";
}
}, [siteData, error]);

/**
* Abstraction to simplify the rendering of the site content after loading
* @return {React.ReactNode} The site content to render
*/
function getSiteContent(): React.ReactNode {
if (errorMessage) {
return <div>{errorMessage}</div>;
} else {
return children;
}
}

return (
<html lang="en">
<body suppressHydrationWarning={true}>
<div className="dark:bg-boxdark-2 dark:text-bodydark">{loading ? <Loader /> : children}</div>
<div className="dark:bg-boxdark-2 dark:text-bodydark">{loading ? <Loader /> : getSiteContent()}</div>
</body>
</html>
);
Expand Down
57 changes: 33 additions & 24 deletions hosting/src/hooks/useTanamSite.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
import {firestore} from "@/firebase"; // this is from you export an initialize the app
import {useState, useEffect} from "react";
import {firestore} from "@/firebase";
import {doc, getDoc} from "firebase/firestore";
import {TanamSite} from "@/models/tanamSite";
import {useParams} from "next/navigation";

/**
* Hook for Tanam site
*
* @param {stirng} site ID of the site
* @return {Object} Tanam site hooks
*/
export function useTanamSite(site: string) {
/**
* Get Tanam site data
*
* @return {Promise<TanamSite | null>} Tanam site data
*/
async function getSite(): Promise<TanamSite | null> {
const docRef = doc(firestore, "tanam", site);
const snap = await getDoc(docRef);
export function useTanamSite() {
const {site} = useParams<{site: string}>() ?? {site: null};
const [siteData, setSiteData] = useState<TanamSite | null>(null);
const [error, setError] = useState<string | null>(null);

if (!snap.exists()) {
return null;
useEffect(() => {
if (site) {
fetchSiteData(site);
} else {
// TODO(Dennis): Redirect to default site ?
setError("No site parameter provided");
return;
}
}, [site]);

const data = {
...snap.data(),
id: snap.id,
};
async function fetchSiteData(siteId: string) {
try {
const docRef = doc(firestore, "tanam", siteId);
const snap = await getDoc(docRef);

return TanamSite.fromJson(data);
if (snap.exists()) {
const data = {
...snap.data(),
id: snap.id,
};
setSiteData(TanamSite.fromJson(data));
} else {
setError("Site not found");
}
} catch (err) {
console.error("Error fetching site data:", err);
setError("No permission to read site data or site not found");
}
}

return {getSite};
return {siteData, error};
}