docs updated

This commit is contained in:
Berkay 2025-05-29 18:19:57 +03:00
parent b63723f1f5
commit cd89b73e80
22 changed files with 510 additions and 0 deletions

View File

@ -0,0 +1,9 @@
# Docs of Evyos management system
## Frontend Docs:
[Frontend](./docs/front.md)
## Backend Docs:
[Backend](./docs/back.md)

0
docs/api.md Normal file
View File

68
docs/front.md Normal file
View File

@ -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)

View File

@ -0,0 +1 @@
# Custom Components

View File

View File

View File

View File

View File

View File

@ -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

View File

View File

View File

View File

View File

View File

View File

@ -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<string | null>(null);
const [jsonText, setJsonText] = useState<string | null>(null);
const {
register,
formState: { errors },
handleSubmit,
} = useForm<LoginFormData>({ resolver: zodResolver(loginSchemaEmail) });
const onSubmit = async (data: LoginFormData) => {
loginHook(startTransition, data, setError, setJsonText, Router, language);
};
return (
<>
<div className="flex h-full min-h-[inherit] flex-col items-center justify-center gap-4">
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
<h2 className="mb-6 text-center text-2xl font-bold text-gray-900">
{translation.login}
</h2>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
<div>
<label
htmlFor="email"
className="block text-sm font-medium text-gray-700"
>
{translation.email}
</label>
<input
{...register("email")}
type="email"
id="email"
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500"
/>
{errors.email && (
<p className="mt-1 text-sm text-red-600">
{errors.email.message}
</p>
)}
</div>
<div>
<label
htmlFor="password"
className="block text-sm font-medium text-gray-700"
>
{translation.password}
</label>
<input
{...register("password")}
type="password"
id="password"
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500"
/>
{errors.password && (
<p className="mt-1 text-sm text-red-600">
{errors.password.message}
</p>
)}
</div>
{error && (
<div className="rounded-md bg-red-50 p-4">
<p className="text-sm text-red-700">{error}</p>
</div>
)}
<button
type="submit"
disabled={isPending}
className="w-full rounded-md bg-indigo-600 px-4 py-2 text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50"
>
{isPending ? translation.pendingMessage : translation.login}
</button>
</form>
</div>
{jsonText && (
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
<h2 className="mb-4 text-center text-xl font-bold text-gray-900">
{translation.responseData}
</h2>
<div className="space-y-2">
{Object.entries(JSON.parse(jsonText)).map(([key, value]) => (
<div key={key} className="flex items-start gap-2">
<strong className="text-gray-700">{key}:</strong>
<span className="text-gray-600">
{typeof value === "object"
? JSON.stringify(value)
: value?.toString() || "N/A"}
</span>
</div>
))}
</div>
</div>
)}
</div>
</>
);
}
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 };
```

View File

@ -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<ClientPageConfig>({
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,
};
}
```

View File

@ -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<ClientMenu>({
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<void>;
updateMenu: (newMenu: ClientMenu) => Promise<boolean>;
}
// 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 };
```

View File

@ -0,0 +1,32 @@
# Online
```typescript
// Create the online hook using the factory
const useContextOnline = createContextHook<ClientOnline>({
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<void>;
updateOnline: (newOnline: ClientOnline) => Promise<boolean>;
}
// 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,
};
}
```

View File

@ -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<ClientSelection>({
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<void>;
updateSelection: (newSelection: ClientSelection) => Promise<boolean>;
}
// 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,
};
}
```

View File

@ -0,0 +1,34 @@
# User
Syncs user info data with redis backend.
```typescript
// Create the selection hook using the factory
const useContextSelection = createContextHook<ClientSelection>({
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<void>;
updateSelection: (newSelection: ClientSelection) => Promise<boolean>;
}
// 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,
};
}
```