Shadcn UI Batch Processing
Shadcn UI Component Library React Radix UI Tailwind CSS Copy-paste Components ปรับแต่งได้ทุกอย่าง Dark Mode Accessibility TypeScript
Batch Processing Pipeline ประมวลผลข้อมูลจำนวนมากเป็นชุด ETL Data Aggregation Report Generation Apache Spark Airflow Dagster dbt
Shadcn UI Setup และ Components
# === Shadcn UI Setup ===
# 1. สร้าง Next.js Project
# npx create-next-app@latest batch-dashboard --typescript --tailwind --eslint
# cd batch-dashboard
# 2. ติดตั้ง Shadcn UI
# npx shadcn-ui@latest init
# - Style: Default
# - Base Color: Slate
# - CSS Variables: Yes
# 3. เพิ่ม Components
# npx shadcn-ui@latest add button
# npx shadcn-ui@latest add table
# npx shadcn-ui@latest add badge
# npx shadcn-ui@latest add card
# npx shadcn-ui@latest add dialog
# npx shadcn-ui@latest add chart
# npx shadcn-ui@latest add tabs
# npx shadcn-ui@latest add progress
# npx shadcn-ui@latest add dropdown-menu
# npx shadcn-ui@latest add toast
# 4. Project Structure
# batch-dashboard/
# ├── src/
# │ ├── app/
# │ │ ├── page.tsx # Dashboard
# │ │ ├── jobs/page.tsx # Jobs List
# │ │ └── layout.tsx # Layout
# │ ├── components/
# │ │ ├── ui/ # Shadcn Components
# │ │ │ ├── button.tsx
# │ │ │ ├── table.tsx
# │ │ │ ├── badge.tsx
# │ │ │ ├── card.tsx
# │ │ │ └── chart.tsx
# │ │ ├── job-table.tsx # Batch Jobs Table
# │ │ ├── job-chart.tsx # Processing Charts
# │ │ └── job-dialog.tsx # Job Config Dialog
# │ └── lib/
# │ └── utils.ts
# ├── tailwind.config.ts
# └── package.json
components_used = {
"Table": "แสดง Batch Jobs: ID, Name, Status, Duration, Records",
"Badge": "แสดง Status: Running (blue), Success (green), Failed (red)",
"Card": "Summary Cards: Total Jobs, Success Rate, Avg Duration",
"Chart": "Bar Chart: Jobs per Hour, Line Chart: Processing Time",
"Dialog": "Job Configuration: Schedule, Parameters, Notifications",
"Progress": "แสดง Progress ของ Running Jobs",
"Tabs": "แยก View: All Jobs, Running, Completed, Failed",
"Toast": "แจ้งเตือนเมื่อ Job เสร็จหรือ Failed",
"DropdownMenu": "Actions: Retry, Cancel, View Logs, Delete",
}
print("Shadcn UI Components for Batch Dashboard:")
for comp, desc in components_used.items():
print(f" [{comp}]")
print(f" {desc}")
Batch Jobs Dashboard Code
# // job-table.tsx — Batch Jobs Table Component
# "use client"
#
# import {
# Table, TableBody, TableCell, TableHead,
# TableHeader, TableRow,
# } from "@/components/ui/table"
# import { Badge } from "@/components/ui/badge"
# import { Button } from "@/components/ui/button"
# import {
# DropdownMenu, DropdownMenuContent,
# DropdownMenuItem, DropdownMenuTrigger,
# } from "@/components/ui/dropdown-menu"
# import { MoreHorizontal, Play, XCircle, Eye } from "lucide-react"
#
# interface BatchJob {
# id: string
# name: string
# status: "running" | "success" | "failed" | "pending"
# startTime: string
# duration: string
# records: number
# progress: number
# }
#
# const statusStyles = {
# running: "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300",
# success: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300",
# failed: "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300",
# pending: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300",
# }
#
# export function JobTable({ jobs }: { jobs: BatchJob[] }) {
# return (
#
#
#
# Job ID
# Name
# Status
# Start Time
# Duration
# Records
# Actions
#
#
#
# {jobs.map((job) => (
#
# {job.id}
# {job.name}
#
#
# {job.status}
#
#
# {job.startTime}
# {job.duration}
# {job.records.toLocaleString()}
#
#
#
#
#
#
# View Logs
# Retry
# Cancel
#
#
#
#
# ))}
#
#
# )
# }
# Batch Processing Pipeline Backend
from dataclasses import dataclass, field
from typing import List, Dict
from datetime import datetime, timedelta
import random
@dataclass
class BatchJob:
id: str
name: str
status: str
start_time: str
duration: str
records: int
progress: int
class BatchPipeline:
"""Batch Processing Pipeline"""
def __init__(self):
self.jobs: List[BatchJob] = []
def add_job(self, job: BatchJob):
self.jobs.append(job)
def summary(self):
total = len(self.jobs)
success = sum(1 for j in self.jobs if j.status == "success")
failed = sum(1 for j in self.jobs if j.status == "failed")
running = sum(1 for j in self.jobs if j.status == "running")
print(f"\n{'='*55}")
print(f"Batch Pipeline Dashboard")
print(f"{'='*55}")
print(f" Total Jobs: {total}")
print(f" Success: {success} ({success/total*100:.0f}%)")
print(f" Failed: {failed} ({failed/total*100:.0f}%)")
print(f" Running: {running}")
total_records = sum(j.records for j in self.jobs)
print(f" Total Records: {total_records:,}")
def show_jobs(self):
print(f"\n {'ID':<10} {'Name':<25} {'Status':<10} {'Records':>10}")
print(f" {'-'*55}")
for job in self.jobs[:10]:
print(f" {job.id:<10} {job.name:<25} {job.status:<10} {job.records:>10,}")
pipeline = BatchPipeline()
job_names = [
"ETL Daily Sales", "User Analytics", "Report Generation",
"Data Warehouse Load", "ML Feature Pipeline",
"Log Aggregation", "Email Campaign Batch",
"Invoice Processing", "Inventory Sync", "Backup Database",
]
statuses = ["success"] * 7 + ["failed"] * 2 + ["running"]
for i in range(10):
job = BatchJob(
id=f"JOB-{1000+i}",
name=job_names[i],
status=random.choice(statuses),
start_time=f"2024-01-{15+i} 06:00",
duration=f"{random.randint(5,120)} min",
records=random.randint(10000, 500000),
progress=random.randint(0, 100),
)
pipeline.add_job(job)
pipeline.summary()
pipeline.show_jobs()
API สำหรับ Dashboard
# batch_api.py — API Endpoints for Dashboard
# Next.js API Routes
# // app/api/jobs/route.ts
# import { NextResponse } from 'next/server'
#
# export async function GET(request: Request) {
# const { searchParams } = new URL(request.url)
# const status = searchParams.get('status')
# const page = parseInt(searchParams.get('page') || '1')
# const limit = parseInt(searchParams.get('limit') || '20')
#
# // Query database
# const jobs = await db.batchJobs.findMany({
# where: status ? { status } : undefined,
# skip: (page - 1) * limit,
# take: limit,
# orderBy: { startTime: 'desc' },
# })
#
# const total = await db.batchJobs.count({
# where: status ? { status } : undefined,
# })
#
# return NextResponse.json({
# jobs,
# pagination: { page, limit, total, pages: Math.ceil(total / limit) },
# })
# }
#
# export async function POST(request: Request) {
# const body = await request.json()
# const job = await db.batchJobs.create({ data: body })
# // Trigger batch processing
# await triggerBatchJob(job.id)
# return NextResponse.json(job, { status: 201 })
# }
# // app/api/jobs/[id]/route.ts
# export async function GET(request: Request, { params }) {
# const job = await db.batchJobs.findUnique({
# where: { id: params.id },
# include: { logs: true, metrics: true },
# })
# return NextResponse.json(job)
# }
#
# export async function PATCH(request: Request, { params }) {
# const body = await request.json()
# if (body.action === 'retry') {
# await retryBatchJob(params.id)
# } else if (body.action === 'cancel') {
# await cancelBatchJob(params.id)
# }
# return NextResponse.json({ ok: true })
# }
api_endpoints = {
"GET /api/jobs": "ดึง Jobs ทั้งหมด filter ตาม status, pagination",
"POST /api/jobs": "สร้าง Job ใหม่ trigger batch processing",
"GET /api/jobs/:id": "ดึง Job detail + logs + metrics",
"PATCH /api/jobs/:id": "Retry, Cancel, Update Job",
"GET /api/jobs/stats": "Summary statistics ของ Jobs",
"GET /api/jobs/:id/logs": "ดึง Logs ของ Job",
"WebSocket /ws/jobs": "Real-time Job status updates",
}
print("API Endpoints:")
for endpoint, desc in api_endpoints.items():
print(f" {endpoint}")
print(f" -> {desc}")
Best Practices
- Shadcn CLI: ใช้ CLI เพิ่ม Components ไม่ต้อง Copy เอง
- Dark Mode: รองรับ Dark Mode ด้วย next-themes
- Data Table: ใช้ @tanstack/react-table กับ Shadcn Table
- Real-time: ใช้ WebSocket หรือ SSE แสดง Status แบบ Real-time
- Pagination: ใช้ Server-side Pagination สำหรับข้อมูลเยอะ
- Error Handling: แสดง Toast เมื่อ Job Failed พร้อม Retry Button
Shadcn UI คืออะไร
Component Library React Radix UI Tailwind CSS Copy-paste Components ปรับแต่งได้ Dark Mode Accessibility TypeScript ไม่ใช่ NPM Package
Batch Processing Pipeline คืออะไร
ประมวลผลข้อมูลจำนวนมากเป็นชุด ETL รายวัน Data Aggregation Report Generation Apache Spark Airflow Dagster dbt
ทำไมต้องใช้ Shadcn UI กับ Batch Processing
Data Table แสดง Batch Jobs Charts Monitoring Badge Status Running Success Failed Dialog Job Configuration Responsive Mobile
Shadcn UI ติดตั้งอย่างไร
npx shadcn-ui@latest init เลือก Style Base Color เพิ่ม Components npx shadcn-ui@latest add button table chart Copy ลง src/components/ui แก้ไขได้
สรุป
Shadcn UI Component Library React Radix UI Tailwind CSS Batch Processing Dashboard Data Table Badge Status Chart Monitoring Dialog Configuration Real-time WebSocket API Next.js Dark Mode TypeScript Responsive
