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

10 KiB
Raw Blame History

uikit

Shared library for BI next.js projects.


Install

yarn add git+https://git.d.aiengines.ir/bi/uikit.git

Update

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

import { toFaDigits, toEnDigits, toFaNumber } from "uikit/utils";

toFaDigits(123456);
toEnDigits("۱۲۳۴۵۶");
toFaNumber(123456);

or

import { toFaDigits } from "uikit";

pagination

required dependencies

yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion react-icons

using

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:

yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion

using:

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:

yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion @tanstack/react-query axios keycloak-js

استفاده از BiProvider

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

keycloakUrl = "https://auth.ibagher.ir";
keycloakRealm = "bi";
permissionUrl = "https://api.d.aiengines.ir/user_api/v1/permissions/list";
updateChecker = false;

نکته: اگر keycloakClientId داده شود، Keycloak فعال می‌شود. اگر permissionClientId داده شود، Permission فعال می‌شود.

برای کنترل دستی:

<BiProvider
  apiBaseUrl="https://api.example.com"
  keycloakEnabled={false}
  permissionEnabled={false}
>
  <YourApp />
</BiProvider>

UpdateChecker

به صورت پیش‌فرض updateChecker خاموش است.

برای فعال کردن:

<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 اجرا شود.

نمونه:

{
  "scripts": {
    "prebuild": "node write-version.js",
    "build": "next build"
  }
}

استفاده از API پایه

import { api, fetcher, configureApi, getApi } from "uikit/core";

اگر از BiProvider استفاده می‌کنی، معمولاً نیازی نیست دستی configureApi را صدا بزنی، چون BiProvider این کار را انجام می‌دهد.

نمونه استفاده مستقیم:

import { api } from "uikit/core";

const response = await api.get("/users");

یا:

import { fetcher } from "uikit/core";

const data = await fetcher("/users");

استفاده از createApi

createApi برای ساختن یک API ساده بر پایه React Query استفاده می‌شود.

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,
    },
  },
});

گرفتن لیست

const { data, isLoading, error } = profileApi.useGet({
  page: 1,
  size: 20,
  is_confirmed: true,
});

این request ساخته می‌شود:

GET /content/rokn/profiles?page=1&size=20&is_confirmed=true

اجرای action

const updateProfile = profileApi.useAction("update");

await updateProfile.mutateAsync({
  id: 10,
  username: "new_username",
});

در این حالت:

PATCH /content/rokn/profiles/10

body:

{
  username: "new_username"
}

id به صورت پیش‌فرض از body حذف می‌شود، چون برای ساختن URL استفاده شده است.


action با همان URL اصلی

اگر action همان URL اصلی را لازم دارد، نیازی نیست url را دوباره بنویسی.

export const identityGenerateApi = createApi({
  key: "identity-generate",
  url: "/content/rokn/identity-generate/logs",

  actions: {
    delete: {
      method: "delete",
    },
  },
});

یعنی:

DELETE /content/rokn/identity-generate/logs

action با FormData

const updateImages = profileApi.useAction("updateImages");

const formData = new FormData();
formData.append("image", file);

await updateImages.mutateAsync({
  id: 10,
  formData,
});

در تعریف action:

updateImages: {
  method: "post",
  url: (id) => `/content/rokn/profile-update/${id}/images`,
  body: ({ formData }) => formData,
}

body مشخص می‌کند چه چیزی واقعاً به عنوان body ارسال شود.


استفاده از Keycloak

import {
  getKeycloakToken,
  loginKeycloak,
  logoutKeycloak,
  updateKeycloakToken,
} from "uikit/core";

const token = getKeycloakToken();

await updateKeycloakToken(30);

loginKeycloak();

logoutKeycloak({
  redirectUri: window.location.origin,
});

استفاده از Permission

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 است.

<Can perm="users:list">
  <UsersList />
</Can>

استفاده از DataTable

DataTable داخل مسیر uikit/table قرار دارد.

dependencyهای لازم:

yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion @tanstack/react-table react-icons

استفاده:

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>
  );
}