uikit/README.md
2026-06-16 07:07:50 +00:00

504 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# uikit
Shared library for BI next.js projects.
---
## Install
```bash
yarn add git+https://git.d.aiengines.ir/bi/uikit.git
```
---
## Update
```bash
yarn upgrade uikit
```
---
# imports
| مسیر | کاربرد | dependency اضافی |
| ------------------ | ------------------------------------- | --------------------------------------- |
| `uikit` | utility functions | - |
| `uikit/utils` | utility functions | - |
| `uikit/pagination` | pagination | Chakra + React + react-icons |
| `uikit/layout` | Header | Chakra + React |
| `uikit/core` | API، BiProvider، Keycloak، Permission | Chakra + React Query + Axios + Keycloak |
| `uikit/table` | DataTable | Chakra + TanStack Table + Pagination |
---
# utils
```js
import { toFaDigits, toEnDigits, toFaNumber } from "uikit/utils";
toFaDigits(123456);
toEnDigits("۱۲۳۴۵۶");
toFaNumber(123456);
```
or
```js
import { toFaDigits } from "uikit";
```
---
# pagination
required dependencies
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion react-icons
```
using
```jsx
import { Pagination, LightPagination, SimplePagination } from "uikit/pagination";
function Page() {
return (
<Pagination
currentPage={1}
totalCount={100}
totalPages={5}
onPageChange={(page) => console.log(page)}
/>
);
}
```
---
# Header
required dependencies:
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
```
using:
```jsx
import { Header } from "uikit/layout";
function AppHeader() {
return (
<Header>
<Header.BrandSection>
<Header.Logo src="/logo.png" />
<Header.Brand>
<Header.Title>عنوان سامانه</Header.Title>
<Header.Description>توضیح کوتاه سامانه</Header.Description>
</Header.Brand>
</Header.BrandSection>
<Header.Bi />
</Header>
);
}
```
---
# استفاده از core
بخش core شامل این موارد است:
* API config
* `createApi`
* `BiProvider`
* Keycloak
* Permission
* React Query provider
* Chakra provider
Required dependencies:
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion @tanstack/react-query axios keycloak-js
```
---
## استفاده از BiProvider
```jsx
import { BiProvider } from "uikit/core";
export default function App() {
return (
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakClientId="front-client"
permissionClientId="permission-client"
>
<YourApp />
</BiProvider>
);
}
```
`BiProvider` به صورت داخلی این کارها را انجام می‌دهد:
* تنظیم base url برای API
* راه‌اندازی Keycloak در صورت فعال بودن
* گرفتن permissionها در صورت فعال بودن
* اضافه کردن `ChakraProvider`
* اضافه کردن `QueryClientProvider`
* اضافه کردن فونت و theme داخلی
* فعال کردن اختیاری `UpdateChecker`
---
## props مربوط به BiProvider
| Prop | توضیح |
| -------------------- | ------------------------------------------------------ |
| `apiBaseUrl` | آدرس اصلی API |
| `keycloakClientId` | client id مربوط به Keycloak |
| `permissionClientId` | client id مربوط به Permission |
| `loading` | کامپوننت loading هنگام init شدن Keycloak یا Permission |
| `updateChecker` | فعال یا غیرفعال کردن بررسی آپدیت |
| `updateCheckerProps` | props مربوط به UpdateChecker |
| `keycloakUrl` | آدرس Keycloak |
| `keycloakRealm` | realm مربوط به Keycloak |
| `permissionUrl` | آدرس API مربوط به permission |
| `keycloakEnabled` | فعال یا غیرفعال کردن Keycloak به صورت دستی |
| `permissionEnabled` | فعال یا غیرفعال کردن Permission به صورت دستی |
---
## مقدارهای پیش‌فرض BiProvider
```js
keycloakUrl = "https://auth.ibagher.ir";
keycloakRealm = "bi";
permissionUrl = "https://api.d.aiengines.ir/user_api/v1/permissions/list";
updateChecker = false;
```
نکته: اگر `keycloakClientId` داده شود، Keycloak فعال می‌شود. اگر `permissionClientId` داده شود، Permission فعال می‌شود.
برای کنترل دستی:
```jsx
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakEnabled={false}
permissionEnabled={false}
>
<YourApp />
</BiProvider>
```
---
# UpdateChecker
به صورت پیش‌فرض `updateChecker` خاموش است.
برای فعال کردن:
```jsx
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakClientId="front-client"
permissionClientId="permission-client"
updateChecker
>
<YourApp />
</BiProvider>
```
اگر `updateChecker` را فعال می‌کنی، پروژه باید فایل version تولید کند. معمولاً باید یک اسکریپت مثل `write-version.js` در root پروژه داشته باشی و در `package.json` پروژه target، قبل از build اجرا شود.
نمونه:
```json
{
"scripts": {
"prebuild": "node write-version.js",
"build": "next build"
}
}
```
---
# استفاده از API پایه
```js
import { api, fetcher, configureApi, getApi } from "uikit/core";
```
اگر از `BiProvider` استفاده می‌کنی، معمولاً نیازی نیست دستی `configureApi` را صدا بزنی، چون `BiProvider` این کار را انجام می‌دهد.
نمونه استفاده مستقیم:
```js
import { api } from "uikit/core";
const response = await api.get("/users");
```
یا:
```js
import { fetcher } from "uikit/core";
const data = await fetcher("/users");
```
---
# استفاده از createApi
`createApi` برای ساختن یک API ساده بر پایه React Query استفاده می‌شود.
```js
import { createApi } from "uikit/core";
export const profileApi = createApi({
key: "profile",
url: "/content/rokn/profiles",
actions: {
update: {
method: "patch",
url: (id) => `/content/rokn/profiles/${id}`,
},
delete: {
method: "delete",
},
generate: {
method: "post",
url: "/content/rokn/generate/profile",
},
updateImages: {
method: "post",
url: (id) => `/content/rokn/profile-update/${id}/images`,
body: ({ formData }) => formData,
},
},
});
```
---
## گرفتن لیست
```jsx
const { data, isLoading, error } = profileApi.useGet({
page: 1,
size: 20,
is_confirmed: true,
});
```
این request ساخته می‌شود:
```txt
GET /content/rokn/profiles?page=1&size=20&is_confirmed=true
```
---
## اجرای action
```jsx
const updateProfile = profileApi.useAction("update");
await updateProfile.mutateAsync({
id: 10,
username: "new_username",
});
```
در این حالت:
```txt
PATCH /content/rokn/profiles/10
```
body:
```js
{
username: "new_username"
}
```
`id` به صورت پیش‌فرض از body حذف می‌شود، چون برای ساختن URL استفاده شده است.
---
## action با همان URL اصلی
اگر action همان URL اصلی را لازم دارد، نیازی نیست `url` را دوباره بنویسی.
```js
export const identityGenerateApi = createApi({
key: "identity-generate",
url: "/content/rokn/identity-generate/logs",
actions: {
delete: {
method: "delete",
},
},
});
```
یعنی:
```txt
DELETE /content/rokn/identity-generate/logs
```
---
## action با FormData
```js
const updateImages = profileApi.useAction("updateImages");
const formData = new FormData();
formData.append("image", file);
await updateImages.mutateAsync({
id: 10,
formData,
});
```
در تعریف action:
```js
updateImages: {
method: "post",
url: (id) => `/content/rokn/profile-update/${id}/images`,
body: ({ formData }) => formData,
}
```
`body` مشخص می‌کند چه چیزی واقعاً به عنوان body ارسال شود.
---
# استفاده از Keycloak
```js
import {
getKeycloakToken,
loginKeycloak,
logoutKeycloak,
updateKeycloakToken,
} from "uikit/core";
const token = getKeycloakToken();
await updateKeycloakToken(30);
loginKeycloak();
logoutKeycloak({
redirectUri: window.location.origin,
});
```
---
# استفاده از Permission
```jsx
import { Can, usePermission } from "uikit/core";
function Page() {
const { can, cannot, permissions } = usePermission();
return (
<>
{can("users:list") && <div>لیست کاربران</div>}
<Can perm="users:create" fallback={null}>
<button>ایجاد کاربر</button>
</Can>
</>
);
}
```
نکته: prop کامپوننت `Can` برابر `perm` است.
```jsx
<Can perm="users:list">
<UsersList />
</Can>
```
---
# استفاده از DataTable
`DataTable` داخل مسیر `uikit/table` قرار دارد.
dependencyهای لازم:
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion @tanstack/react-table react-icons
```
استفاده:
```jsx
import { DataTable } from "uikit/table";
function UsersTable({ data, columns }) {
return (
<DataTable
data={data}
columns={columns}
page={1}
size={20}
pagination={{
totalCount: 100,
totalPages: 5,
}}
onPageChange={(page) => console.log(page)}
getRowId={(row) => String(row.id)}
enableSelection
showIndex
>
<DataTable.Topbar>
<DataTable.Title>لیست کاربران</DataTable.Title>
<DataTable.Spacer />
<DataTable.Actions>
<DataTable.SelectAll />
</DataTable.Actions>
</DataTable.Topbar>
<DataTable.Content>
<DataTable.Table />
<DataTable.Pagination />
</DataTable.Content>
</DataTable>
);
}
```
---