Refactor Part 1

This commit is contained in:
phntxx 2021-03-21 18:05:24 +01:00
parent bc897a6bfb
commit 9fef36eae3
18 changed files with 314 additions and 310 deletions

166
src/lib/fetcher.tsx Normal file
View file

@ -0,0 +1,166 @@
import { useCallback, useEffect, useState } from "react";
import { ISearchProviderProps } from "../components/searchBar";
import { IBookmarkGroupProps } from "../components/bookmarkGroup";
import { IAppCategoryProps } from "../components/appCategory";
import { IAppProps } from "../components/app";
import { IThemeProps } from "./theme";
import { IImprintProps } from "../components/imprint";
const errorMessage = "Failed to load data.";
const inProduction = process.env.NODE_ENV === "production";
const handleResponse = (response: any) => {
if (response.ok) return response.json();
throw new Error(errorMessage);
};
export interface ISearchProviderDataProps {
providers: Array<ISearchProviderProps>;
error: string | boolean;
}
export interface IBookmarkDataProps {
groups: Array<IBookmarkGroupProps>;
error: string | boolean;
}
export interface IAppDataProps {
categories: Array<IAppCategoryProps>;
apps: Array<IAppProps>;
error: string | boolean;
}
export interface IThemeDataProps {
themes: Array<IThemeProps>;
error: string | boolean;
}
export interface IImprintDataProps {
imprint: IImprintProps;
error: string | boolean;
}
/**
* Default values for the respective state variables
*/
const defaults = {
app: {
categories: [],
apps: [],
error: false,
},
bookmark: {
groups: [],
error: false,
},
search: {
providers: [],
error: false,
},
theme: {
themes: [],
error: false,
},
imprint: {
imprint: {
name: { text: "", link: "" },
address: { text: "", link: "" },
phone: { text: "", link: "" },
email: { text: "", link: "" },
url: { text: "", link: "" },
},
error: false,
},
};
/**
* Handles fetch errors by returning the error message.
* @param {string} type - The type of fetch request that threw an error
* @param {Error} error - The error itself
*/
const handleError = (status: string, error: Error) => {
switch (status) {
case "apps":
return { ...defaults.app, error: error.message }
case "bookmark":
return { ...defaults.bookmark, error: error.message }
case "searchProvider":
return { ...defaults.search, error: error.message }
case "theme":
return { ...defaults.theme, error: error.message }
case "imprint":
return { ...defaults.imprint, error: error.message }
default:
break;
}
}
/**
* Fetches all of the data by doing fetch requests
*/
const fetchProduction = Promise.all([
fetch("/data/apps.json").then(handleResponse).catch((error: Error) => handleError("apps", error)),
fetch("/data/bookmarks.json").then(handleResponse).catch((error: Error) => handleError("bookmark", error)),
fetch("/data/search.json").then(handleResponse).catch((error: Error) => handleError("searchProvider", error)),
fetch("/data/themes.json").then(handleResponse).catch((error: Error) => handleError("theme", error)),
fetch("/data/imprint.json").then(handleResponse).catch((error: Error) => handleError("imprint", error)),
]);
/**
* Fetches all of the data by importing it (only available in development)
*/
const fetchDevelopment = Promise.all([
import("../data/apps.json"),
import("../data/bookmarks.json"),
import("../data/search.json"),
import("../data/themes.json"),
import("../data/imprint.json"),
]);
/**
* Fetches app, bookmark, search, theme and imprint data and returns it.
* @returns all of the data the function was able to fetch and the callback function to refresh the data
*/
export const useFetcher = () => {
const [appData, setAppData] = useState<IAppDataProps>(defaults.app);
const [bookmarkData, setBookmarkData] = useState<IBookmarkDataProps>(
defaults.bookmark
);
const [
searchProviderData,
setSearchProviderData,
] = useState<ISearchProviderDataProps>(defaults.search);
const [themeData, setThemeData] = useState<IThemeDataProps>(defaults.theme);
const [imprintData, setImprintData] = useState<IImprintDataProps>(
defaults.imprint
);
const callback = useCallback(() => {
(inProduction ? fetchProduction : fetchDevelopment).then(
([appData, bookmarkData, searchData, themeData, imprintData]: any) => {
(appData.error) ? setAppData(appData) : setAppData({ ...appData, error: false });
(bookmarkData.error) ? setBookmarkData(bookmarkData) : setBookmarkData({ ...bookmarkData, error: false });
(searchData.error) ? setSearchProviderData(searchData) : setSearchProviderData({ ...searchData, error: false });
(themeData.error) ? setThemeData(themeData) : setThemeData({ ...themeData, error: false });
(imprintData.error) ? setImprintData(imprintData) : setImprintData({ ...imprintData, error: false });
}
);
}, []);
useEffect(() => callback(), [callback]);
return {
appData,
bookmarkData,
searchProviderData,
themeData,
imprintData, callback
};
};
export default useFetcher;

33
src/lib/theme.tsx Normal file
View file

@ -0,0 +1,33 @@
export interface IThemeProps {
label: string;
value: number;
mainColor: string;
accentColor: string;
backgroundColor: string;
}
const defaultTheme: IThemeProps = {
label: "Classic",
value: 0,
mainColor: "#000000",
accentColor: "#1e272e",
backgroundColor: "#ffffff",
};
export const setTheme = (theme: string) => {
if (theme !== undefined) localStorage.setItem("theme", theme);
window.location.reload();
};
const getTheme = () => {
let selectedTheme = defaultTheme;
if (localStorage.getItem("theme") != null) {
selectedTheme = JSON.parse(localStorage.getItem("theme") || "{}");
}
return selectedTheme;
};
const selectedTheme = getTheme();
export default selectedTheme;