Chuyển tới nội dung chính

Quy tắc coding

Naming Conventions

Đối tượngConventionVí dụ
File ComponentPascalCaseCategoryForm.tsx, NewsTab.tsx
File logic/helperkebab-casecategory.schema.ts, use-hook.ts
Thư mục (Folders)kebab-casecategory-list/, auth-callback/
React ComponentPascalCaseCategoryForm
Biến, hàm, propscamelCasesearchValue, handleSubmit
Event Handlershandle / onhandleFilter, onDelete
Biến Booleanis, has, canisLoading, hasPermission
Type/InterfacePascalCaseNotificationItem
Hằng số/enumUPPER_SNAKE_CASENOTIFY_TYPE
API string keysnake_casevin_order_noti

Chi tiết về Naming

  • Event Handlers:
    • Hàm xử lý logic trong component: handle + Verb (ví dụ: handleClick, handleFilterChange).
    • Props callback (nhận từ công ngoài): on + Verb (ví dụ: onClick, onSuccess).
  • Biến Boolean: Sử dụng prefix is, has, should, can (ví dụ: isLoading, hasPermission).
  • Thư mục: Luôn dùng kebab-case cho tên thư mục.

Import Rules

// ✅ Import trực tiếp từ @vppos/core
import { Button, Input } from "@vppos/core/ui/react";
import { useDebounce } from "@vppos/core/hooks";
import { toastUtils } from "@vppos/core/utils";

// ❌ Không re-export qua file barrel trong app
// ❌ Không tạo lại component/hook đã có trong core

Do & Don't

API Calls

// ✅ Dùng RTK Query
const { data, isLoading } = useGetProductsQuery({ page: 1 });

// ❌ Không gọi API trực tiếp
const data = await fetch("/api/products");
const data = await axios.get("/api/products");

Toast

// ✅ Dùng toastUtils
import { toastUtils } from "@vppos/core/utils";
toastUtils.success("Thành công");

// ❌ Không import toast từ react-toastify
import { toast } from "react-toastify";

Error Handling

// ✅ Dùng helper
import { getApiErrorMessage, getApiError, setFormErrors } from "@vppos/core/utils";

try {
await createProduct(data).unwrap();
toastUtils.success("Tạo thành công");
} catch (err) {
const apiError = getApiError(err);
if (apiError?.fieldErrors) {
setFormErrors(setError, apiError.fieldErrors);
}
toastUtils.error(getApiErrorMessage(err));
}

Date/Time

// ✅ Dùng dayjs
import dayjs from "dayjs";
const now = dayjs();
const formatted = formatDate(date);

// ❌ Không dùng new Date()
const now = new Date();

JSX Handlers

// ✅ Tách handler
const handleDelete = async () => {
await deleteProduct(id).unwrap();
};
<Button onClick={() => handleDelete()}>Delete</Button>

// ❌ Không viết async inline
<Button onClick={async () => { await deleteProduct(id) }}>Delete</Button>

Tailwind

// ✅ Dùng theme colors
<div className="text-primary-500 bg-primary-50" />

// ❌ Không hard-code hex
<div style={{ color: "#f97316" }} />

Git Commits

# Format: <type>: <subject>
# Types: feat | fix | docs | style | refactor | perf | test | build | ci | chore

git commit -m "feat: add store selection page"
git commit -m "fix: auto-select first store"
git commit -m "refactor: simplify login flow"