25 KiB
📋 แผนการพัฒนา Frontend (NestJS) - LCBP3-DMS v1.4.0
📋 แผนการพัฒนา Frontend (Next.js) - LCBP3-DMS v1.4.0
🎯 ภาพรวมโครงการ
พัฒนา Frontend สำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System) ที่ทันสมัย responsive และใช้งานง่าย รองรับการจัดการเอกสารที่ซับซ้อน มี Dashboard แบบ Real-time และระบบ Workflow Visualization
📐 สถาปัตยกรรมระบบ
Technology Stack
- Framework: Next.js 14+ (App Router, React 18+, TypeScript, ESM)
- Styling: Tailwind CSS + PostCSS
- Component Library: shadcn/ui (Radix UI)
- State Management:
- Server State: TanStack Query (React Query)
- Global Client State: Zustand
- Form State: React Hook Form + Zod
- Data Fetching: Axios + TanStack Query
- Authentication: NextAuth.js (JWT Strategy)
- File Upload: React Dropzone
- Tables: TanStack Table
- Charts: Recharts
- Date Picker: date-fns + shadcn/ui Calendar
- Icons: Lucide React
- Testing:
- Unit/Integration: Vitest + React Testing Library
- E2E: Playwright
- API Mocking: Mock Service Worker (MSW)
โครงสร้างโปรเจกต์
app/
├── (public)/ # Public routes (Landing, Login)
│ ├── page.tsx # Landing Page
│ └── login/ # Login Page
├── (protected)/ # Protected routes
│ ├── layout.tsx # App Shell (Navbar + Sidebar)
│ ├── dashboard/ # Dashboard
│ ├── correspondences/ # Correspondence Management
│ ├── rfas/ # RFA Management
│ ├── drawings/ # Drawing Management
│ ├── circulations/ # Circulation Management
│ ├── transmittals/ # Transmittal Management
│ ├── search/ # Advanced Search
│ ├── reports/ # Reports
│ ├── admin/ # Admin Panel
│ └── profile/ # User Profile
├── api/ # API Routes (if needed)
components/
├── ui/ # shadcn/ui components
├── features/ # Feature-specific components
│ ├── auth/
│ ├── correspondence/
│ ├── rfa/
│ ├── drawing/
│ ├── circulation/
│ └── common/
└── layouts/ # Layout components
lib/
├── api/ # API client & hooks
├── stores/ # Zustand stores
├── utils/ # Utility functions
├── hooks/ # Custom hooks
└── types/ # TypeScript types
public/
├── images/
└── fonts/
🗓️ แผนการพัฒนาแบบ Phase-Based
Phase 0: Setup & Infrastructure (สัปดาห์ที่ 1)
Milestone: สร้างโครงสร้างพื้นฐานและ Development Environment
Tasks:
T0.1 Initialize Next.js Project
- สร้างโปรเจกต์ด้วย
create-next-app:npx create-next-app@latest lcbp3-frontend --typescript --tailwind --app --src-dir=false - เลือก Options:
- ✅ TypeScript
- ✅ ESLint
- ✅ Tailwind CSS
- ✅ App Router
- ✅ Import alias (@/*)
- Setup .gitignore, README.md
- Deliverable: ✅ โปรเจกต์เริ่มต้นพร้อม
T0.2 Install Core Dependencies
# State Management & Data Fetching
npm install @tanstack/react-query zustand
npm install axios
npm install react-hook-form @hookform/resolvers zod
# UI Components & Styling
npm install clsx tailwind-merge
npm install lucide-react
npm install date-fns
# File Upload
npm install react-dropzone
# Authentication
npm install next-auth
# Development Tools
npm install -D @types/node
- Deliverable: ✅ Dependencies ติดตั้งสมบูรณ์
T0.3 Setup shadcn/ui
npx shadcn-ui@latest init
- เลือก Style: Default
- เลือก Base Color: Slate
- ติดตั้ง Components เบื้องต้น:
npx shadcn-ui@latest add button input label card table dropdown-menu npx shadcn-ui@latest add dialog sheet toast alert npx shadcn-ui@latest add form select textarea checkbox npx shadcn-ui@latest add calendar popover - Deliverable: ✅ shadcn/ui พร้อมใช้งาน
T0.4 Configure Tailwind CSS
- แก้ไข
tailwind.config.ts:- เพิ่ม Custom Colors (ตาม Brand)
- เพิ่ม Custom Fonts (ภาษาไทย: Noto Sans Thai)
- Configure Container, Spacing
- สร้าง
app/globals.cssพร้อม Custom Styles - Deliverable: ✅ Tailwind พร้อมใช้
T0.5 Setup Development Environment
- สร้าง
.env.local:NEXT_PUBLIC_API_URL=http://backend.np-dms.work/api NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET=... - Setup ESLint Rules (ไทย Comments OK)
- Setup Prettier
- Setup VS Code Settings
- Deliverable: ✅ Dev Environment พร้อม
T0.6 Setup Git & Docker
- Push โปรเจกต์ไปยัง Gitea (git.np-dms.work)
- สร้าง Dockerfile สำหรับ Next.js:
FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build EXPOSE 3000 CMD ["npm", "start"] - สร้าง docker-compose.yml (เชื่อม Network
lcbp3) - Deliverable: ✅ Project อยู่ใน Git + Docker พร้อม
Phase 1: Authentication & App Shell (สัปดาห์ที่ 2-3)
Milestone: ระบบ Login และ Layout หลัก
Tasks:
T1.1 Setup API Client
-
สร้าง
lib/api/client.ts:import axios from "axios"; export const apiClient = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_URL, headers: { "Content-Type": "application/json", }, }); // Request Interceptor (Add JWT Token) apiClient.interceptors.request.use((config) => { const token = localStorage.getItem("access_token"); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // Response Interceptor (Handle Errors) apiClient.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // Redirect to login window.location.href = "/login"; } return Promise.reject(error); } ); -
Deliverable: ✅ API Client พร้อมใช้
T1.2 Setup TanStack Query
-
สร้าง
app/providers.tsx:"use client"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { useState } from "react"; export function Providers({ children }: { children: React.ReactNode }) { const [queryClient] = useState( () => new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, // 1 minute refetchOnWindowFocus: false, }, }, }) ); return ( <QueryClientProvider client={queryClient}>{children}</QueryClientProvider> ); } -
Wrap ใน
app/layout.tsx -
Deliverable: ✅ React Query พร้อม
T1.3 Create Auth Store (Zustand)
-
สร้าง
lib/stores/auth-store.ts:import { create } from "zustand"; import { persist } from "zustand/middleware"; interface User { user_id: number; username: string; email: string; first_name: string; last_name: string; primary_organization_id: number; permissions: string[]; } interface AuthStore { user: User | null; token: string | null; setAuth: (user: User, token: string) => void; clearAuth: () => void; hasPermission: (permission: string) => boolean; } export const useAuthStore = create<AuthStore>()( persist( (set, get) => ({ user: null, token: null, setAuth: (user, token) => { set({ user, token }); localStorage.setItem("access_token", token); }, clearAuth: () => { set({ user: null, token: null }); localStorage.removeItem("access_token"); }, hasPermission: (permission) => { const user = get().user; return user?.permissions.includes(permission) || false; }, }), { name: "auth-storage", } ) ); -
Deliverable: ✅ Auth Store พร้อม
T1.4 Create Login Page
-
สร้าง
app/(public)/login/page.tsx:"use client"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { useRouter } from "next/navigation"; import { useAuthStore } from "@/lib/stores/auth-store"; import { apiClient } from "@/lib/api/client"; const loginSchema = z.object({ username: z.string().min(1, "กรุณากรอกชื่อผู้ใช้"), password: z.string().min(1, "กรุณากรอกรหัสผ่าน"), }); export default function LoginPage() { const router = useRouter(); const setAuth = useAuthStore((state) => state.setAuth); const form = useForm({ resolver: zodResolver(loginSchema), }); const handleLogin = async (data: z.infer<typeof loginSchema>) => { try { const response = await apiClient.post("/auth/login", data); const { access_token, user } = response.data; setAuth(user, access_token); router.push("/dashboard"); } catch (error) { console.error("Login failed:", error); // แสดง Toast Error } }; return ( <div className="flex min-h-screen items-center justify-center"> <form onSubmit={form.handleSubmit(handleLogin)} className="w-96"> {/* Form Fields */} </form> </div> ); } -
Deliverable: ✅ หน้า Login พร้อม
T1.5 Create Landing Page
- สร้าง
app/(public)/page.tsx:- Hero Section พร้อมข้อมูลโครงการ
- Feature Highlights
- CTA Button → Login
- ใช้ Tailwind + Animations
- Deliverable: ✅ Landing Page สวยงาม
T1.6 Create Protected Layout (App Shell)
-
สร้าง
app/(protected)/layout.tsx:"use client"; import { useEffect } from "react"; import { useRouter } from "next/navigation"; import { useAuthStore } from "@/lib/stores/auth-store"; import Navbar from "@/components/layouts/navbar"; import Sidebar from "@/components/layouts/sidebar"; export default function ProtectedLayout({ children, }: { children: React.ReactNode; }) { const router = useRouter(); const user = useAuthStore((state) => state.user); useEffect(() => { if (!user) { router.push("/login"); } }, [user, router]); if (!user) return null; return ( <div className="flex h-screen"> <Sidebar /> <div className="flex flex-1 flex-col"> <Navbar /> <main className="flex-1 overflow-y-auto p-6">{children}</main> </div> </div> ); } -
Deliverable: ✅ App Shell พร้อม
T1.7 Create Navbar Component
- สร้าง
components/layouts/navbar.tsx:- แสดงชื่อระบบ
- แสดงชื่อผู้ใช้ + Avatar
- Dropdown Menu:
- Profile
- Settings
- Logout
- Responsive (Mobile Hamburger Menu)
- Deliverable: ✅ Navbar พร้อม
T1.8 Create Sidebar Component
- สร้าง
components/layouts/sidebar.tsx:- เมนูหลัก:
- Dashboard
- Correspondences
- RFAs
- Drawings (Shop & Contract)
- Circulations
- Transmittals
- Search
- Reports
- เมนู Admin (แสดงตามสิทธิ์):
- Users
- Roles & Permissions
- Master Data
- Document Numbering
- เมนูหลัก:
- Collapsible Sidebar
- Active State Highlighting
- Deliverable: ✅ Sidebar พร้อม
Phase 2: Dashboard & Common Components (สัปดาห์ที่ 4)
Milestone: Dashboard และ Reusable Components
Tasks:
T2.1 Create Reusable Components
components/features/common/data-table.tsx:- ใช้ TanStack Table
- รองรับ Pagination, Sorting, Filtering
- Responsive
components/features/common/file-upload.tsx:- ใช้ React Dropzone
- รองรับ Multi-file Upload
- Drag & Drop
- Progress Bar
components/features/common/status-badge.tsx:- แสดง Status แบบสีสัน (Draft, Submitted, Approved)
components/features/common/permission-guard.tsx:- ซ่อน/แสดง Component ตามสิทธิ์
- Deliverable: ✅ Reusable Components พร้อม
T2.2 Create Dashboard Page
- สร้าง
app/(protected)/dashboard/page.tsx:- KPI Cards Section:
- จำนวนเอกสารทั้งหมด
- งานที่รอดำเนินการ
- เอกสารที่เกินกำหนด
- RFA ที่รออนุมัติ
- My Tasks Table:
- ดึงข้อมูลจาก
/api/circulations/my-tasks(ใช้v_user_tasks) - แสดงรายการงานที่ต้องทำ (Pending, In Progress)
- Columns: Document Number, Title, Type, Status, Deadline, Actions
- คลิกแถวแล้วไปยังหน้า Detail
- ดึงข้อมูลจาก
- Recent Activity Feed:
- ดึงข้อมูลจาก
/api/audit-logs/user/:userId - แสดง 10 รายการล่าสุด
- ดึงข้อมูลจาก
- KPI Cards Section:
- Deliverable: ✅ Dashboard ครบถ้วน
T2.3 Create API Hooks
-
สร้าง
lib/api/hooks/use-my-tasks.ts:import { useQuery } from "@tanstack/react-query"; import { apiClient } from "../client"; export function useMyTasks() { return useQuery({ queryKey: ["my-tasks"], queryFn: async () => { const response = await apiClient.get("/circulations/my-tasks"); return response.data; }, }); } -
สร้าง Hooks เพิ่มเติม:
use-dashboard-stats.tsuse-recent-activity.ts
-
Deliverable: ✅ API Hooks พร้อม
Phase 3: Correspondence Management (สัปดาห์ที่ 5-6)
Milestone: ระบบจัดการเอกสารโต้ตอบ
Tasks:
T3.1 Create Correspondence List Page
- สร้าง
app/(protected)/correspondences/page.tsx:- Data Table แสดงรายการเอกสาร
- Columns:
- Document Number (คลิกไปยัง Detail)
- Title
- Type
- Status (Badge)
- Originator
- Date
- Actions (View, Edit, Delete)
- Filters:
- ประเภทเอกสาร (Dropdown)
- สถานะ (Dropdown)
- วันที่ (Date Range Picker)
- องค์กร (Dropdown)
- Pagination (Server-side)
- Search Box
- Create Button (ตรวจสิทธิ์)
- Deliverable: ✅ หน้ารายการเอกสาร
T3.2 Create Correspondence Detail Page
- สร้าง
app/(protected)/correspondences/[id]/page.tsx:- Header Section:
- Document Number (ใหญ่)
- Status Badge
- Action Buttons: Edit, Delete, Export PDF
- Metadata Section:
- Title, Description
- Document Date, Issued Date, Received Date
- Originator, Recipients (TO/CC)
- Due Date (ถ้ามี)
- Revision History:
- แสดง Revisions ทั้งหมดเป็น Timeline
- แต่ละ Revision แสดง: Revision Number, Date, Changes, User
- Attachments:
- แสดงไฟล์แนบทั้งหมด
- กำหนดไฟล์หลัก (Main Document) ด้วยไอคอน
- ปุ่ม Download
- References:
- แสดงเอกสารที่อ้างถึง (Links)
- Tags:
- แสดง Tags แบบ Chips
- Activity Log:
- แสดง Audit Log ของเอกสารนี้
- Header Section:
- Deliverable: ✅ หน้า Detail ครบถ้วน
T3.3 Create Correspondence Form (Create/Edit)
- สร้าง
app/(protected)/correspondences/create/page.tsx: - สร้าง
app/(protected)/correspondences/[id]/edit/page.tsx: - Form Fields:
- Basic Info:
- Correspondence Type (Dropdown)
- Title (Text)
- Description (Textarea)
- Document Date (Date Picker)
- Recipients:
- TO: Multi-select Organizations
- CC: Multi-select Organizations
- References:
- Search & Select เอกสารอื่นๆ
- Tags:
- Autocomplete Tag Input
- Attachments:
- File Upload (Multi-file)
- กำหนด Main Document (Radio)
- Deadline:
- Due Date (Date Picker)
- Basic Info:
- Validation ด้วย Zod
- Submit → API → Redirect to Detail
- Deliverable: ✅ ฟอร์มสร้าง/แก้ไข
T3.4 Create Status Management
- ใน Detail Page เพิ่มปุ่ม Status Actions:
- Draft → Submit (Document Control)
- Submit → Close (Admin)
- Submit → Cancel (Admin + Dialog ให้กรอกเหตุผล)
- แสดง Confirmation Dialog ก่อนเปลี่ยนสถานะ
- Deliverable: ✅ เปลี่ยนสถานะได้
Phase 4: RFA & Workflow Visualization (สัปดาห์ที่ 7-8)
Milestone: ระบบ RFA และ Workflow
Tasks:
T4.1 Create RFA List Page
- สร้าง
app/(protected)/rfas/page.tsx:- คล้าย Correspondence List
- Columns เพิ่มเติม:
- RFA Type (DWG, DOC, MAT)
- Approval Status (Badge)
- Approval Code (1A, 3R, etc.)
- Filters:
- RFA Type
- Status
- Approval Code
- Deliverable: ✅ หน้ารายการ RFA
T4.2 Create RFA Detail Page
- สร้าง
app/(protected)/rfas/[id]/page.tsx:- คล้าย Correspondence Detail
- เพิ่ม Section:
- Shop Drawings (สำหรับ RFA_DWG):
- แสดงรายการ Shop Drawings ที่เชื่อมโยง
- แสดง Revision ของแต่ละแบบ
- Link ไปยัง Shop Drawing Detail
- Workflow Visualization (ดูรายละเอียดใน T4.3)
- Shop Drawings (สำหรับ RFA_DWG):
- Deliverable: ✅ หน้า Detail RFA
T4.3 Create Workflow Visualization Component
- สร้าง
components/features/rfa/workflow-visualizer.tsx:- Layout: Steps แนวนอน (Timeline)
- Step States:
- ✅ Completed: สีเขียว, ไอคอน Check
- ⏳ Active: สีฟ้า, ปุ่ม Action เปิดใช้งาน
- ⏸️ Pending: สีเทา, ปุ่ม disabled
- ❌ Rejected: สีแดง
- Step Info Card (เมื่อคลิก):
- Organization
- Assigned User
- Action Type (Review, Approve)
- Status
- Comments
- Completed Date
- Actions (สำหรับ Active Step):
- ปุ่ม "อนุมัติ" (Approve)
- ปุ่ม "ปฏิเสธ" (Reject)
- Dialog ให้กรอก Comments
- Admin Override:
- ปุ่ม "ไปยังขั้นตอนต่อไป" (Skip Step)
- ปุ่ม "ย้อนกลับ" (Previous Step)
- Deliverable: ✅ Workflow Component พร้อม
T4.4 Create RFA Form (Create/Edit)
- สร้าง
app/(protected)/rfas/create/page.tsx: - Form Fields:
- RFA Type (Dropdown)
- Title, Description
- Document Date
- Shop Drawings Section (สำหรับ RFA_DWG):
- Search & Select Shop Drawings
- แสดง Revisions ที่มี (Dropdown)
- เพิ่มได้หลายแบบ
- Attachments
- Workflow Template (Dropdown)
- Submit → สร้าง RFA + Start Workflow
- Deliverable: ✅ ฟอร์ม RFA พร้อม
T4.5 Implement Workflow Actions API
-
สร้าง
lib/api/hooks/use-rfa-workflow.ts:import { useMutation, useQueryClient } from "@tanstack/react-query"; import { apiClient } from "../client"; export function useCompleteWorkflowStep() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ rfaId, stepNumber, action, comments }) => { const response = await apiClient.post( `/rfas/${rfaId}/workflow/steps/${stepNumber}/complete`, { action, comments } ); return response.data; }, onSuccess: (_, variables) => { queryClient.invalidateQueries(["rfa", variables.rfaId]); queryClient.invalidateQueries(["my-tasks"]); }, }); } -
Hooks เพิ่มเติม:
use-reject-workflow-step.tsuse-start-workflow.ts
-
Deliverable: ✅ Workflow Actions ทำงานได้
Phase 5: Drawing Management (สัปดาห์ที่ 9)
Milestone: ระบบจัดการแบบ
Tasks:
T5.1 Create Shop Drawing List Page
- สร้าง
app/(protected)/drawings/shop/page.tsx:- Data Table:
- Drawing Number
- Title
- Main Category
- Sub Category
- Current Revision
- Actions
- Filters:
- Category (Dropdown)
- Sub Category (Dropdown)
- Create Button
- Data Table:
- Deliverable: ✅ หน้ารายการ Shop Drawings
T5.2 Create Shop Drawing Detail Page
- สร้าง
app/(protected)/drawings/shop/[id]/page.tsx:- Header: Drawing Number, Title
- Current Revision Info:
- Revision Number, Date
- Description
- Attachments (PDF, DWG)
- Contract Drawing References:
- แสดง Contract Drawings ที่อ้างถึง
- Links ไปยัง Contract Drawing Detail
- Revision History:
- แสดง Revisions ทั้งหมดเป็น Timeline
- Related RFAs:
- แสดง RFAs ที่เชื่อมโยงกับแบบนี้
- Deliverable: ✅ หน้า Detail Shop Drawing
T5.3 Create Shop Drawing Form
- สร้าง
app/(protected)/drawings/shop/create/page.tsx: - Form Fields:
- Drawing Number (Auto-generate หรือ Manual)
- Title
- Main Category (Dropdown)
- Sub Category (Dropdown, dependent on Main)
- Contract Drawing References:
- Search & Select Contract Drawings (Multi-select)
- Revision Info:
- Revision Number (Auto)
- Revision Label (A, B, C)
- Description
- Attachments:
- Upload PDF (Main)
- Upload DWG (Optional)
- Upload Other Files
- Deliverable: ✅ ฟอร์ม Shop Drawing
T5.4 Create Contract Drawing List & Detail
- สร้าง
app/(protected)/drawings/contract/page.tsx:- Data Table:
- Drawing Number
- Title
- Volume
- Category
- Sub Category
- Filters:
- Volume (Dropdown)
- Category (Dropdown)
- Data Table:
- สร้าง
app/(protected)/drawings/contract/[id]/page.tsx:- แสดง Metadata
- Attachments
- Referenced By:
- แสดง Shop Drawings ที่อ้างถึงแบบนี้
- Deliverable: ✅ Contract Drawing Pages
Phase 6: Circulation & Transmittal (สัปดาห์ที่ 10)
Milestone: ระบบใบเวียนและเอกสารนำส่ง
Tasks:
T6.1 Create Circulation List Page
- สร้าง
app/(protected)/circulations/page.tsx:- Data Table:
- Circulation Number
- Subject
- Status (Badge)
- Created By
- Created Date
- Filters:
- Status
- Date Range
- Data Table:
- Deliverable: ✅ หน้ารายการใบเวียน
T6.2 Create Circulation Detail & Workflow
- สร้าง
app/(protected)/circulations/[id]/page.tsx:- Header: Circulation Number, Subject, Status
- Linked Correspondence:
- Link ไปยังเอกสารต้นทาง
- Workflow Visualization:
- คล้าย RFA Workflow
- แสดง Steps:
- Organization
- Assigned Users (Main, Action, Information)
- Status
- Comments
- Deadline
- Actions (สำหรับ Assigned User):
- ปุ่ม "ดำเนินการเสร็จสิ้น" (Complete)
- Dialog ให้กรอก Comments
- Close Circulation (Document Control):
- ปุ่ม "ปิดใบเวียน" (เมื่อตอบกลับองค์กรผู้ส่งแล้ว)
- Deliverable: ✅ หน้า Detail ใบเวียน