diff --git a/README.md b/README.md index e69de29..3d28e80 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,9 @@ +# Docs of Evyos management system + +## Frontend Docs: + +[Frontend](./docs/front.md) + +## Backend Docs: + +[Backend](./docs/back.md) diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/front.md b/docs/front.md new file mode 100644 index 0000000..330a2ee --- /dev/null +++ b/docs/front.md @@ -0,0 +1,68 @@ +## Frontend + +### /apifetchers + +Sends requests to external APIs + +### Layouts + +- Authentication Layout => prefix...auth +- Dashboard Layout => prefix...dashboard +- ` [...page] => gets string from url and renders page` + +### /api + +- Internal API Fetchers +- Send requests from user's browser to /apifetchers + +# Reusable components + +- [Mutual Components](./frontDocs/MutualComponents.md) +- [Custom Components](./frontDocs/CustomComponents.md) + +# Hooks + +Hooks that are used in client side actions + +# Languages Models + +Languages models that are used in the project + +- [Mutual Languages Models](./frontDocs/MutualLanguagesModels.md) + +# Pages + +!!!Only one of them is allowed +Pages that are used in the project. + +- [Mutual Pages](./frontDocs/MutualPages.md) +- [Multi Pages](./frontDocs/MultiPages.md) +- [Single Pages](./frontDocs/SinglePages.md) + +# Schemas + +Schemas that are used in the project + +- [Mutual Schemas](./frontDocs/MutualSchemas.md) +- [Custom Schemas](./frontDocs/CustomSchemas.md) + +# Types + +Types that are used in the project + +- [Mutual Types](./frontDocs/MutualTypes.md) +- [Custom Types](./frontDocs/CustomTypes.md) + +# Validations + +Validations that are used in the project + +- [Mutual Validations](./frontDocs/MutualValidations.md) +- [Custom Validations](./frontDocs/CustomValidations.md) + +# Web Pages + +Web pages that are used in the project + +- [Single Web Pages](./frontDocs/SingleWebPages.md) +- [Multi Web Pages](./frontDocs/MultiWebPages.md) diff --git a/docs/frontDocs/CustomComponents.md b/docs/frontDocs/CustomComponents.md new file mode 100644 index 0000000..847717a --- /dev/null +++ b/docs/frontDocs/CustomComponents.md @@ -0,0 +1 @@ +# Custom Components diff --git a/docs/frontDocs/CustomSchemas.md b/docs/frontDocs/CustomSchemas.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/CustomTypes.md b/docs/frontDocs/CustomTypes.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/CustomValidations.md b/docs/frontDocs/CustomValidations.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/MultiPages.md b/docs/frontDocs/MultiPages.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/MultiWebPages.md b/docs/frontDocs/MultiWebPages.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/MutualComponents.md b/docs/frontDocs/MutualComponents.md new file mode 100644 index 0000000..27a4ca3 --- /dev/null +++ b/docs/frontDocs/MutualComponents.md @@ -0,0 +1,31 @@ +# Mutual + +## Contexts + +- [Component Contexts](./docs/contexts/component_contexts.md) +- [Component Menu](./docs/contexts/component_menu.md) +- [Component User](./docs/contexts/component_user.md) +- [Component Online](./docs/contexts/component_online.md) +- [Component Selection](./docs/contexts/component_selection.md) + +## Language Selection + +- Creates a button on top right corner of the screen that allows user to switch languages. + +## Loader + +- Creates a loading screen that shows while data is being fetched. + +## Navigators + +- Links thats redirect to given url with Icon Wrap and key for the component + +## shadcnui + +- UI that is used in the project + +## Views + +- Card View +- Table View +- Mutual Dependencies diff --git a/docs/frontDocs/MutualLanguagesModels.md b/docs/frontDocs/MutualLanguagesModels.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/MutualPages.md b/docs/frontDocs/MutualPages.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/MutualSchemas.md b/docs/frontDocs/MutualSchemas.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/MutualTypes.md b/docs/frontDocs/MutualTypes.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/MutualValidations.md b/docs/frontDocs/MutualValidations.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/Navigators.md b/docs/frontDocs/Navigators.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/frontDocs/SingleWebPages.md b/docs/frontDocs/SingleWebPages.md new file mode 100644 index 0000000..4addc26 --- /dev/null +++ b/docs/frontDocs/SingleWebPages.md @@ -0,0 +1,237 @@ +# Web Pages + +- Web pages that are used in the project + +## Directories: + +``` +-| PageName + -| hook.ts + -| language.ts + -| page.tsx + -| schemas.ts + -| types.ts +``` + +### hook.ts: + +```typescript +export function loginHook( + startTransition: any, + data: any, + setError: any, + setJsonText: any, + Router: any, + lang: LanguageTypes +) { + try { + const sendData = { ...data }; + startTransition(() => { + fetch("/api/login/email", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(sendData), + }) + .then((response) => { + if (response.status === 200) { + response.json().then((data) => { + setTimeout(() => { + Router.push(`/panel/dashboard`); + }, 100); + }); + } else { + response.json().then((data) => { + setError(data?.message); + }); + } + }) + .catch(() => {}); + }); + } catch (error) { + setError("An error occurred during login"); + } +} +``` + +### language.ts: + +```typescript +export const loginTranslation = { + tr: { + email: "E-Posta", + password: "Şifre", + rememberMe: "Beni Hatırla", + login: "Giriş Yap", + successMessage: "Giriş Yapıldı", + errorMessage: "Giriş Yapılmadı", + pendingMessage: "Giriş Yapılıyor...", + responseData: "Giriş Verileri", + }, + en: { + email: "Email", + password: "Password", + rememberMe: "Remember Me", + login: "Login", + successMessage: "Login completed successfully", + errorMessage: "Login failed", + pendingMessage: "Logging in...", + responseData: "Response Data", + }, +}; +``` + +### page.tsx: + +```typescript +"use client"; +import { useState, useTransition } from "react"; +import { useRouter } from "next/navigation"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { LoginFormData } from "./types"; +import { loginSchemaEmail } from "./schemas"; +import { loginTranslation } from "./language"; +import { loginHook } from "./hook"; +import { AuthPageProps } from "@/validations/mutual/auth/props"; + +function Login({ language }: AuthPageProps) { + const Router = useRouter(); + const translation = loginTranslation[language]; + + const [isPending, startTransition] = useTransition(); + const [error, setError] = useState(null); + const [jsonText, setJsonText] = useState(null); + + const { + register, + formState: { errors }, + handleSubmit, + } = useForm({ resolver: zodResolver(loginSchemaEmail) }); + const onSubmit = async (data: LoginFormData) => { + loginHook(startTransition, data, setError, setJsonText, Router, language); + }; + + return ( + <> +
+
+

+ {translation.login} +

+
+
+ + + {errors.email && ( +

+ {errors.email.message} +

+ )} +
+
+ + + {errors.password && ( +

+ {errors.password.message} +

+ )} +
+ {error && ( +
+

{error}

+
+ )} + +
+
+ {jsonText && ( +
+

+ {translation.responseData} +

+
+ {Object.entries(JSON.parse(jsonText)).map(([key, value]) => ( +
+ {key}: + + {typeof value === "object" + ? JSON.stringify(value) + : value?.toString() || "N/A"} + +
+ ))} +
+
+ )} +
+ + ); +} + +export default Login; +``` + +### schemas.ts: + +```typescript +import { z } from "zod"; + +const loginSchemaEmail = z.object({ + email: z.string().email("Invalid email address"), + password: z.string().min(5, "Password must be at least 5 characters"), + rememberMe: z.boolean().optional().default(false), +}); + +const loginSchemaPhone = z.object({ + phone: z.string().regex(/^[0-9]{10}$/, "Invalid phone number"), + password: z.string().min(5, "Password must be at least 5 characters"), + rememberMe: z.boolean().optional().default(false), +}); + +export { loginSchemaEmail, loginSchemaPhone }; +``` + +### types.ts: + +```typescript +type LoginFormData = { + email: string; + password: string; + rememberMe?: boolean; +}; + +type LoginFormDataPhone = { + phone: string; + password: string; + rememberMe?: boolean; +}; + +export type { LoginFormData, LoginFormDataPhone }; +``` diff --git a/docs/frontDocs/contexts/component_contexts.md b/docs/frontDocs/contexts/component_contexts.md new file mode 100644 index 0000000..15fee68 --- /dev/null +++ b/docs/frontDocs/contexts/component_contexts.md @@ -0,0 +1,24 @@ +# Context + +Syncs each step of user's session with redis backend. + +```typescript +// Create the config hook using the factory +const useContextConfig = createContextHook({ + endpoint: "/context/page/config", + contextName: "config", + enablePeriodicRefresh: false, +}); + +// Wrapper hook that adapts the generic hook to the expected interface +export function useConfig(): UseConfigResult { + const { data, isLoading, error, refresh, update } = useContextConfig(); + return { + configData: data, + isLoading, + error, + refresh, + update, + }; +} +``` diff --git a/docs/frontDocs/contexts/component_menu.md b/docs/frontDocs/contexts/component_menu.md new file mode 100644 index 0000000..05af52f --- /dev/null +++ b/docs/frontDocs/contexts/component_menu.md @@ -0,0 +1,40 @@ +# Menu + +Syncs each step of left menu actions with redis backend. + +```typescript +// Create the menu hook using the factory +const useContextMenu = createContextHook({ + endpoint: "/context/page/menu", + contextName: "menu", + extractAvailableItems: (data) => data.selectionList || [], + enablePeriodicRefresh: false, +}); + +// Custom hook for menu data with the expected interface +interface UseMenuResult { + menuData: ClientMenu | null; + availableApplications: string[]; + isLoading: boolean; + error: string | null; + refreshMenu: () => Promise; + updateMenu: (newMenu: ClientMenu) => Promise; +} + +// Wrapper hook that adapts the generic hook to the expected interface +export function useMenu(): UseMenuResult { + const { data, availableItems, isLoading, error, refresh, update } = + useContextMenu(); + + return { + menuData: data, + availableApplications: availableItems, + isLoading, + error, + refreshMenu: refresh, + updateMenu: update, + }; +} + +export { checkContextPageMenu, setContextPageMenu }; +``` diff --git a/docs/frontDocs/contexts/component_online.md b/docs/frontDocs/contexts/component_online.md new file mode 100644 index 0000000..5f5c952 --- /dev/null +++ b/docs/frontDocs/contexts/component_online.md @@ -0,0 +1,32 @@ +# Online + +```typescript +// Create the online hook using the factory +const useContextOnline = createContextHook({ + endpoint: "/context/page/online", + contextName: "online", + enablePeriodicRefresh: true, + refreshInterval: 5 * 60 * 1000, // 5 minutes +}); + +// Custom hook for online data with the expected interface +interface UseOnlineResult { + onlineData: ClientOnline | null; + isLoading: boolean; + error: string | null; + refreshOnline: () => Promise; + updateOnline: (newOnline: ClientOnline) => Promise; +} + +// Wrapper hook that adapts the generic hook to the expected interface +export function useOnline(): UseOnlineResult { + const { data, isLoading, error, refresh, update } = useContextOnline(); + return { + onlineData: data, + isLoading, + error, + refreshOnline: refresh, + updateOnline: update, + }; +} +``` diff --git a/docs/frontDocs/contexts/component_selection.md b/docs/frontDocs/contexts/component_selection.md new file mode 100644 index 0000000..20f93c9 --- /dev/null +++ b/docs/frontDocs/contexts/component_selection.md @@ -0,0 +1,34 @@ +# Selection + +Syncs each step of duty or occupant selections of user with redis backend. + +```typescript +// Create the selection hook using the factory +const useContextSelection = createContextHook({ + endpoint: "/context/dash/selection", + contextName: "selection", + enablePeriodicRefresh: false, +}); + +// Custom hook for selection data with the expected interface +interface UseSelectionResult { + selectionData: ClientSelection | null; + isLoading: boolean; + error: string | null; + refreshSelection: () => Promise; + updateSelection: (newSelection: ClientSelection) => Promise; +} + +// Wrapper hook that adapts the generic hook to the expected interface +export function useSelection(): UseSelectionResult { + const { data, isLoading, error, refresh, update } = useContextSelection(); + + return { + selectionData: data, + isLoading, + error, + refreshSelection: refresh, + updateSelection: update, + }; +} +``` diff --git a/docs/frontDocs/contexts/component_user.md b/docs/frontDocs/contexts/component_user.md new file mode 100644 index 0000000..ebc6dfa --- /dev/null +++ b/docs/frontDocs/contexts/component_user.md @@ -0,0 +1,34 @@ +# User + +Syncs user info data with redis backend. + +```typescript +// Create the selection hook using the factory +const useContextSelection = createContextHook({ + endpoint: "/context/dash/selection", + contextName: "selection", + enablePeriodicRefresh: false, +}); + +// Custom hook for selection data with the expected interface +interface UseSelectionResult { + selectionData: ClientSelection | null; + isLoading: boolean; + error: string | null; + refreshSelection: () => Promise; + updateSelection: (newSelection: ClientSelection) => Promise; +} + +// Wrapper hook that adapts the generic hook to the expected interface +export function useSelection(): UseSelectionResult { + const { data, isLoading, error, refresh, update } = useContextSelection(); + + return { + selectionData: data, + isLoading, + error, + refreshSelection: refresh, + updateSelection: update, + }; +} +```