> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/developer-guide-en/pjt-prepare/publish-your-docs/bo-development-guide.md).

# BO Development Guide

This section explains the programming standards used to maintain a consistent development style for X2BEE Solution 3.0. Follow these guidelines to maintain a consistent code style and to keep development efficient and readable when working with the solution.

Along with principles for code reusability, type safety, and performance optimization for developing Next.js 15-based applications, this section explains the project structure and development standards.

***

## Route Creation Guide

* Uses NEXT15 - [App Router](https://nextjs.org/docs/app)
* URLs are created by combining names based on the Abbreviations Glossary, following the folder hierarchy
* Primary classification: *<mark style="color:red;">module</mark>* , secondary classification: *<mark style="color:green;">task</mark>*
  * e.g.) /src/app/\[pageType]/*<mark style="color:red;">**display**</mark>*/*<mark style="color:green;">**standard-category-mgmt**</mark>*/page.tsx → /display/standard-category-mgmt
* Page component (page.tsx) → minimize the use of "use client"

Standard structure example:

<table data-header-hidden><thead><tr><th width="95"></th><th width="133"></th><th width="85"></th><th width="80"></th><th></th></tr></thead><tbody><tr><td>app</td><td>(multi-lang)</td><td>module</td><td>task</td><td><a href="https://nextjs.org/docs/app/building-your-application/routing/route-groups">Group</a> for applying multiple languages</td></tr><tr><td></td><td>(task-popup)</td><td></td><td></td><td>Task popup <a href="https://nextjs.org/docs/app/building-your-application/routing/route-groups">group</a> e.g.) Display connection set popup</td></tr><tr><td></td><td>[pageType]</td><td></td><td></td><td><p>pageType: 'page' | 'tab' | 'pagepopup'</p><p>If a default value is not entered, the layout sets it to 'page' by default</p></td></tr><tr><td></td><td>popup</td><td></td><td></td><td>Common and general popups</td></tr><tr><td></td><td>auth</td><td></td><td></td><td>Authorization-related (login page)</td></tr><tr><td></td><td>error</td><td></td><td></td><td>Error page</td></tr></tbody></table>

***

## Component Creation Guide

* Primary classification: *<mark style="color:red;">**module**</mark>* , secondary classification: *<mark style="color:green;">**task**</mark>*
  * e.g.) /src/components/*<mark style="color:red;">**display**</mark>*/*<mark style="color:green;">**display-category-mgmt**</mark>* /display-category-tree.tsx
* Define required types and schemas for each task in separate files

{% code title="standard-category-schema.ts" lineNumbers="true" %}

```typescript
export const StandardCategoryGoodsAttrSchema = z.object({
  stdCtgNo: StringSchema({ key: 'display.standardCategory.field.stdCtgNo' })
});
export type StandardCategoryGoodsAttrSchemaType = z.infer<typeof StandardCategoryGoodsAttrSchema>;
```

{% endcode %}

* Declare types that are judged to be used only inside the component within the component

{% code title="StandardCategoryGoodsAttrGrid.tsx" lineNumbers="true" %}

```typescript
type Props = {stdCtgNo: string };
export default function StandardCategoryGoodsAttrGrid({ stdCtgNo }: Props) { 
... }
```

{% endcode %}

* Configure components finely, based on task and state, to minimize re-render issues
* You can explicitly manage a component's life-cycle by setting a key
  * It's recommended to make keys detailed (using a simple ID alone can cause key duplication)

Example:

{% code title="usage-example.tsx" lineNumbers="true" %}

```jsx
<CommonSectionBox>
  <StandardCategoryForm
    standardCategory={standardCategory}
    key={`standard_category_form_${standardCategory.stdCtgNo}`}
  />
</CommonSectionBox>
```

{% endcode %}

Example inside a component:

{% code title="StandardCategoryForm.tsx" lineNumbers="true" %}

```tsx
const StandardCategoryForm = ({ standardCategory }: Props) => {
  const { data: formData, success } = useSafeParse(
    StandardCategorySchema.safeParse(standardCategory)
  );
  ...
}
```

{% endcode %}

***

## API Call Guide

* Use REST API
* Use types extracted from Zod schemas
* Returns in Promise format by default

**GET example:**

{% code title="api-get.ts" lineNumbers="true" %}

```ts
export const fetchDisplaySubCategoryList = async (
  params: DisplayCategorySearchSchemaType
) => 
  (await restApi.get(
    `${API_PATH}/getSubCategoryList`, 
    { 
      params 
    }
  )) as GridResponse<DisplayCategorySchemaType[]>;
```

{% endcode %}

**POST/PUT/DELETE example:**

{% code title="api-post.ts" lineNumbers="true" %}

```ts
export const fetchRegistDisplayCategory = async (
  body: DisplayCategorySchemaType
) => 
  (await restApi.post(
    API_PATH, 
    {
     body 
    }
  )) as ResponseEntity<DisplayCategorySchemaType>;
```

{% endcode %}

**Handler and Client API Usage Rules:**

* handleResponse, handleGridResponse: output default data via isSuccess inside getData
  * isSuccess: boolean
  * code: string
  * message: string
  * getData: () => T
* clientRestApi: used for clientRequest, with loading enabled by default option
  * api: Promise
  * options(optional) → loading: true

Usage example:

{% code title="useClientRestApi-example.tsx" lineNumbers="true" %}

```ts
const clientRestApi = useClientRestApi();

const fetchGridData = useCallback(async () => {
  const api = async () => {
    const response = await fetchDisplaySubCategoryList({ dispCtgNo: displayCategory.dispCtgNo });
    const { getData } = handleGridResponse(response as GridResponse<DisplayCategorySchemaType[]>);
    const payload = getData() as X2beeSimplePaginationDataType<DisplayCategorySchemaType>;
    setGridPayload(payload.rows);
  };

  await clientRestApi({
    api,
    // options: { loading: true } // options can be omitted
  });
}, [displayCategory.dispCtgNo]);
```

{% endcode %}

***

## Custom Hooks Creation Guide

* Create when reuse is needed and using hooks is required
* When logic complexity requires separate management (first consider Utils; consider whether Hooks are used internally)

***

## Utils Creation Guide

* When reuse is needed
* When hooks are not used internally
* When the logic is complex and needs to be managed separately
* When usage is needed on the server side

***

##
