操作
バグ #950
未完了【948-2】フロントエンド基盤実装 - React/TypeScript/Tailwind
ステータス:
新規
優先度:
急いで
担当者:
-
開始日:
2025-07-31
期日:
進捗率:
0%
予定工数:
説明
【子チケット2】フロントエンド基盤実装¶
🎯 目的¶
React + TypeScript + Tailwind CSSベースのフロントエンド基盤を実装し、既存の画面設計を統合する。
📋 実装内容¶
1. フロントエンド基盤セットアップ¶
cd /root/form-automation-system/frontend
# Vite + React + TypeScript プロジェクト作成
npm create vite@latest . -- --template react-ts
# 必要パッケージインストール
npm install \
@tailwindcss/forms \
@headlessui/react \
@heroicons/react \
react-router-dom \
zustand \
@tanstack/react-query \
react-hook-form \
@hookform/resolvers \
zod \
recharts \
date-fns \
clsx \
lucide-react
# 開発依存関係
npm install -D \
tailwindcss \
postcss \
autoprefixer \
@types/node \
eslint \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser \
prettier \
prettier-plugin-tailwindcss
2. プロジェクト構造¶
frontend/
├── src/
│ ├── components/ # 再利用可能コンポーネント
│ │ ├── ui/ # 基本UIコンポーネント
│ │ ├── forms/ # フォームコンポーネント
│ │ ├── charts/ # グラフ・チャートコンポーネント
│ │ └── layout/ # レイアウトコンポーネント
│ ├── pages/ # ページコンポーネント
│ │ ├── Dashboard/ # ダッシュボード
│ │ ├── Tasks/ # タスク管理
│ │ ├── Data/ # データ管理
│ │ ├── Settings/ # 設定画面
│ │ └── Monitoring/ # 監視・ログ
│ ├── hooks/ # カスタムフック
│ ├── stores/ # Zustand状態管理
│ ├── services/ # API通信サービス
│ ├── types/ # TypeScript型定義
│ ├── utils/ # ユーティリティ関数
│ └── styles/ # CSS・Tailwind設定
├── public/ # 静的ファイル
├── Dockerfile # 本番用Dockerfile
├── Dockerfile.dev # 開発用Dockerfile
└── package.json
3. 主要設定ファイル¶
Tailwind設定(tailwind.config.js)¶
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
// LINEデザイン言語準拠カラーパレット
'line-green': {
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#06c755', // LINE Primary Green
600: '#059142',
700: '#047836',
800: '#065f46',
900: '#064e3b',
},
'line-gray': {
50: '#f9fafb',
100: '#f3f4f6',
200: '#e5e7eb',
300: '#d1d5db',
400: '#9ca3af',
500: '#6b7280',
600: '#4b5563',
700: '#374151',
800: '#1f2937',
900: '#111827',
}
},
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
},
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
},
},
},
plugins: [
require('@tailwindcss/forms'),
],
}
TypeScript設定(tsconfig.json)¶
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@/components/*": ["./src/components/*"],
"@/pages/*": ["./src/pages/*"],
"@/hooks/*": ["./src/hooks/*"],
"@/stores/*": ["./src/stores/*"],
"@/services/*": ["./src/services/*"],
"@/types/*": ["./src/types/*"],
"@/utils/*": ["./src/utils/*"]
}
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
4. 基本コンポーネント実装¶
レイアウトコンポーネント(src/components/layout/Layout.tsx)¶
import React from 'react';
import { Outlet } from 'react-router-dom';
import { Sidebar } from './Sidebar';
import { Header } from './Header';
export const Layout: React.FC = () => {
return (
<div className="min-h-screen bg-gray-50">
<Sidebar />
<div className="lg:pl-64">
<Header />
<main className="py-6">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<Outlet />
</div>
</main>
</div>
</div>
);
};
サイドバーナビゲーション¶
import React from 'react';
import { NavLink } from 'react-router-dom';
import {
HomeIcon,
CogIcon,
ChartBarIcon,
DocumentTextIcon,
ClipboardDocumentListIcon,
} from '@heroicons/react/24/outline';
const navigation = [
{ name: 'ダッシュボード', href: '/', icon: HomeIcon },
{ name: 'タスク管理', href: '/tasks', icon: ClipboardDocumentListIcon },
{ name: 'データ管理', href: '/data', icon: DocumentTextIcon },
{ name: '監視・ログ', href: '/monitoring', icon: ChartBarIcon },
{ name: '設定', href: '/settings', icon: CogIcon },
];
export const Sidebar: React.FC = () => {
return (
<div className="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-64 lg:flex-col">
<div className="flex grow flex-col gap-y-5 overflow-y-auto border-r border-gray-200 bg-white px-6 pb-4">
<div className="flex h-16 shrink-0 items-center">
<h1 className="text-xl font-bold text-line-green-500">
Form Automation
</h1>
</div>
<nav className="flex flex-1 flex-col">
<ul role="list" className="flex flex-1 flex-col gap-y-7">
<li>
<ul role="list" className="-mx-2 space-y-1">
{navigation.map((item) => (
<li key={item.name}>
<NavLink
to={item.href}
className={({ isActive }) =>
clsx(
isActive
? 'bg-line-green-50 text-line-green-600'
: 'text-gray-700 hover:text-line-green-600 hover:bg-gray-50',
'group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold'
)
}
>
<item.icon className="h-6 w-6 shrink-0" />
{item.name}
</NavLink>
</li>
))}
</ul>
</li>
</ul>
</nav>
</div>
</div>
);
};
5. 状態管理(Zustand)¶
アプリケーション状態¶
// src/stores/appStore.ts
import { create } from 'zustand';
interface AppState {
isLoading: boolean;
error: string | null;
user: User | null;
setLoading: (loading: boolean) => void;
setError: (error: string | null) => void;
setUser: (user: User | null) => void;
}
export const useAppStore = create<AppState>((set) => ({
isLoading: false,
error: null,
user: null,
setLoading: (loading) => set({ isLoading: loading }),
setError: (error) => set({ error }),
setUser: (user) => set({ user }),
}));
タスク状態管理¶
// src/stores/taskStore.ts
import { create } from 'zustand';
interface TaskState {
tasks: Task[];
runningTasks: Task[];
completedTasks: Task[];
selectedTask: Task | null;
fetchTasks: () => Promise<void>;
createTask: (task: CreateTaskRequest) => Promise<void>;
updateTask: (id: string, updates: Partial<Task>) => Promise<void>;
deleteTask: (id: string) => Promise<void>;
setSelectedTask: (task: Task | null) => void;
}
export const useTaskStore = create<TaskState>((set, get) => ({
tasks: [],
runningTasks: [],
completedTasks: [],
selectedTask: null,
fetchTasks: async () => {
// API実装
},
createTask: async (task) => {
// API実装
},
updateTask: async (id, updates) => {
// API実装
},
deleteTask: async (id) => {
// API実装
},
setSelectedTask: (task) => set({ selectedTask: task }),
}));
6. API通信サービス¶
API基盤クライアント¶
// src/services/api.ts
import axios from 'axios';
const API_BASE_URL = import.meta.env.VITE_API_URL || '/api';
export const apiClient = axios.create({
baseURL: API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
// Request interceptor
apiClient.interceptors.request.use(
(config) => {
const token = localStorage.getItem('auth_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// Response interceptor
apiClient.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem('auth_token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
7. ルーティング設定¶
// src/App.tsx
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Layout } from '@/components/layout/Layout';
import { Dashboard } from '@/pages/Dashboard';
import { Tasks } from '@/pages/Tasks';
import { Data } from '@/pages/Data';
import { Settings } from '@/pages/Settings';
import { Monitoring } from '@/pages/Monitoring';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Dashboard />} />
<Route path="tasks/*" element={<Tasks />} />
<Route path="data/*" element={<Data />} />
<Route path="settings/*" element={<Settings />} />
<Route path="monitoring/*" element={<Monitoring />} />
</Route>
</Routes>
</BrowserRouter>
</QueryClientProvider>
);
}
export default App;
✅ 完了条件¶
基盤セットアップ¶
- Vite + React + TypeScript プロジェクト作成
- 必要パッケージインストール完了
- Tailwind CSS設定完了
プロジェクト構造¶
- ディレクトリ構造作成
- 基本設定ファイル配置
- TypeScript設定完了
基本コンポーネント¶
- Layout・Header・Sidebar実装
- ナビゲーション機能実装
- 基本UIコンポーネント実装
状態管理・ルーティング¶
- Zustand状態管理セットアップ
- React Router設定
- API通信基盤実装
動作確認¶
- 開発サーバー起動確認
- 基本ページ表示確認
- ナビゲーション動作確認
🔄 次のステップ¶
フロントエンド基盤完了後、子チケット3(バックエンドAPI実装)に移行。
Claude Code実行プロンプト:
フォーム自動化システムのフロントエンド基盤を実装してください。React + TypeScript + Tailwind CSS + Zustand構成で、既存の画面設計仕様を継承し、LINEデザイン言語準拠のモダンなUIを構築してください。ディレクトリ構造作成から基本コンポーネント実装まで段階的に進め、各ステップの完了を報告してください。
表示するデータがありません
操作