Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .autorc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
# プロジェクト固有の環境設定

# Node.js v20を使用
if command -v nvm &> /dev/null; then
nvm use 20 2>/dev/null || echo "Node.js v20が見つかりません。'nvm install 20'を実行してください。"
fi

echo "🚀 Node.js $(node --version) を使用しています"
echo "📁 Agile Studio Talent Management プロジェクト環境を読み込みました"
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@
amplify_outputs*
amplifyconfiguration*
.amplify-hosting/
amplify_outputs.json
# .envファイルを.gitignoreに追加
.env.development
.env.local
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.19.3
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20
101 changes: 101 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## プロジェクト概要

AWS Amplify Gen2とReact Router v7を使用したモダンな人材管理システム。
React 19、TypeScript、Tailwind CSS、shadcn/uiを使用し、SSRが有効化されている。

## 開発コマンド

```bash
# 開発サーバー起動 (http://localhost:5173)
npm run dev

# プロダクションビルド
npm run build

# 型チェック
npm run typecheck

# リント実行
npm run lint

# フォーマット実行
npm run format

# テスト実行
npm run test
```

## アーキテクチャ構成

### フロントエンド構造

- `app/root.tsx` - Amplify設定を含むアプリケーションルート
- `app/routes.ts` - React Router v7のネストルーティング定義
- `app/routes/protected/layout.tsx` - 認証保護されたレイアウト
- `app/components/` - shadcn/uiを含む再利用可能コンポーネント
- `app/lib/amplify-client.ts` - Amplifyクライアント設定

### バックエンド構造

- `amplify/backend.ts` - Amplifyバックエンド設定
- `amplify/data/resource.ts` - GraphQLスキーマとデータモデル
- `amplify/auth/resource.ts` - 認証設定

### データモデル

- **Account**: 従業員プロフィール(名前、メール、所属、居住地)
- **Project**: プロジェクト情報(期間、概要)
- **ProjectTechnology**: 技術カタログ
- **ProjectAssignment**: アカウント-プロジェクト間の多対多関係
- **ProjectTechnologyLink**: プロジェクト-技術間の多対多関係

## 重要な設定

- **認証**: AWS Cognito(メールベース)
- **データベース**: DynamoDB(Amplify管理)
- **権限**: 所有者ベース + 管理者グループ
- **SSR**: React Router v7で有効化
- **スタイル**: Tailwind CSS v4 + shadcn/ui(New Yorkスタイル)

## 主要機能

1. **アカウント管理**: CRUD操作 + CSV一括インポート
2. **プロジェクト管理**: プロジェクト情報とアサインメント管理
3. **技術管理**: プロジェクト技術カタログ
4. **認証**: 保護されたルートとロールベースアクセス

## 開発パターン

- ファイルベースルーティング(React Router v7)
- コンポーネント合成(shadcn/ui使用)
- 型安全なデータ操作(Amplify生成型使用)
- カスタムフック活用
- サーバーサイドレンダリング対応

## 設計書の参照・更新

### 設計書の場所

- `docs/design/システム設計書.md` - システム全体の設計概要
- `docs/design/技術アーキテクチャ.md` - 技術スタック・アーキテクチャ詳細
- `docs/design/データベース設計書.md` - DynamoDB設計・データモデル
- `docs/design/API設計書.md` - GraphQL API・型定義

### 開発時のルール

1. **機能追加・変更前**: 必ず関連する設計書を参照し、既存設計との整合性を確認
2. **実装後**: 設計に影響がある変更の場合は対応する設計書を更新
3. **新機能**: 新しいエンティティやAPIを追加する場合は設計書に追記
4. **アーキテクチャ変更**: 技術スタックや構成に変更がある場合は設計書を更新

### 設計書更新のタイミング

- データモデル変更時(amplify/data/resource.ts変更)
- 新しいページ・機能追加時
- 認証・認可ルール変更時
- 技術スタック変更時(package.json、設定ファイル変更)
- パフォーマンス最適化実装時
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,39 @@ Agile Studio のメンバーのスキルや経験、プロジェクトアサイ

## 開発環境セットアップ

### 必要なバージョン

- **Node.js**: v20.x以上(React Router v7要件)
- **npm**: v10.x以上

### Node.js環境切り替え

#### 方法1: 自動設定スクリプト使用

```bash
# プロジェクトディレクトリで実行
source .autorc
```

#### 方法2: nvm使用(推奨)

```bash
# Node.js v20をインストール(未インストールの場合)
nvm install 20

# プロジェクト用Node.js v20使用
nvm use

# 確認
node --version # v20.x.x が表示されることを確認
```

### 1. 依存関係のインストール

プロジェクトのルートディレクトリで以下のコマンドを実行し、必要なパッケージをインストールします。

```bash
npm install
npm ci
```

### 2. 開発サーバーの起動
Expand All @@ -28,6 +55,22 @@ npm run dev

アプリケーションは `http://localhost:5173` で利用可能になります。

### その他の開発コマンド

```bash
# 型チェック(Amplify設定後)
npm run typecheck

# リント実行
npm run lint

# フォーマット実行
npm run format

# テスト実行
npm run test
```

## ビルド

本番用のビルドを作成するには、以下のコマンドを実行します。
Expand All @@ -51,6 +94,20 @@ npm run build

デプロイが完了すると、Amplify によって提供される URL でアプリケーションにアクセスできるようになります。CI/CD パイプラインも自動的に設定され、選択したブランチへのプッシュをトリガーに自動でビルドとデプロイが実行されます。

## 📚 ドキュメント

- [CLAUDE.md](./CLAUDE.md) - Claude Code用プロジェクト概要
- [システム設計書](./docs/design/システム設計書.md)
- [技術アーキテクチャ](./docs/design/技術アーキテクチャ.md)
- [データベース設計書](./docs/design/データベース設計書.md)
- [API設計書](./docs/design/API設計書.md)

## ⚠️ 注意事項

- Node.js v20未満では警告が表示されます
- 初回起動時は`amplify_outputs.json`が存在しないため型エラーが出ますが正常です
- Amplify設定後に`npx ampx generate`で型定義を生成してください

---

Built with ❤️ using React Router and AWS Amplify.
13 changes: 12 additions & 1 deletion app/components/nav-user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
SidebarMenuItem,
useSidebar,
} from "~/components/ui/sidebar";
import { mockAuth } from "~/lib/amplify-mock";
export function NavUser({
user,
}: {
Expand All @@ -31,7 +32,17 @@ export function NavUser({
const navigate = useNavigate();
const handleLogout = async () => {
console.log("Logging out...");
await signOut();

// モック認証モードの場合
if (import.meta.env.VITE_USE_MOCK_AUTH === "true") {
await mockAuth.signOut();
// Cookieも削除
document.cookie = "mockAuthToken=; path=/; max-age=0";
} else {
// 本番モード
await signOut();
}

navigate("/login");
};

Expand Down
53 changes: 53 additions & 0 deletions app/lib/amplify-mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Mock Amplify configuration for development without AWS
export const mockAmplifyConfig = {
Auth: {
Cognito: {
userPoolId: "mock-user-pool",
userPoolClientId: "mock-client-id",
identityPoolId: "mock-identity-pool",
},
},
};

// Mock user for development
export const mockUser = {
userId: "mock-user-123",
username: import.meta.env.VITE_MOCK_USER_EMAIL || "[email protected]",
signInDetails: {
loginId: import.meta.env.VITE_MOCK_USER_EMAIL || "[email protected]",
},
};

// Mock authentication functions
export const mockAuth = {
getCurrentUser: async () => {
if (import.meta.env.VITE_USE_MOCK_AUTH === "true") {
const isLoggedIn = localStorage.getItem("mockAuthToken");
if (isLoggedIn) {
return mockUser;
}
throw new Error("Not authenticated");
}
throw new Error("Mock auth not enabled");
},

signIn: async (_credentials: { username: string; password: string }) => {
if (import.meta.env.VITE_USE_MOCK_AUTH === "true") {
// Accept any credentials in mock mode
localStorage.setItem("mockAuthToken", "mock-token");
return {
isSignedIn: true,
nextStep: { signInStep: "DONE" },
};
}
throw new Error("Mock auth not enabled");
},

signOut: async () => {
if (import.meta.env.VITE_USE_MOCK_AUTH === "true") {
localStorage.removeItem("mockAuthToken");
return {};
}
throw new Error("Mock auth not enabled");
},
};
22 changes: 14 additions & 8 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { useEffect } from "react";
import { ToasterProvider } from "~/components/toaster-provider";
import config from "../amplify_outputs.json";

Amplify.configure(config, { ssr: true });
// Configure Amplify based on environment
if (import.meta.env.VITE_USE_MOCK_AUTH !== "true") {
Amplify.configure(config, { ssr: true });
}

export const links: Route.LinksFunction = () => [
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
Expand All @@ -42,12 +45,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
<Links />
</head>
<body>
<Authenticator.Provider>
<ThemeProvider>
{children}
<ToasterProvider />
</ThemeProvider>
</Authenticator.Provider>
{children}
<ScrollRestoration />
<Scripts />
</body>
Expand All @@ -65,7 +63,15 @@ export default function App() {
}
});
}, []);
return <Outlet />;

return (
<Authenticator.Provider>
<ThemeProvider>
<Outlet />
<ToasterProvider />
</ThemeProvider>
</Authenticator.Provider>
);
}

export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
Expand Down
5 changes: 4 additions & 1 deletion app/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
} from "@react-router/dev/routes";

export default [
layout("routes/auth/layout.tsx", [route("login", "./routes/auth/login.tsx")]),
layout("routes/auth/layout.tsx", [
route("login", "./routes/auth/login.tsx"),
route("login-mock", "./routes/auth/login-mock.tsx"),
]),
layout("./routes/protected/layout.tsx", [
index("routes/home.tsx"),
route("accounts", "routes/accounts.tsx"),
Expand Down
40 changes: 40 additions & 0 deletions app/routes/accounts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,46 @@ export async function action({ request }: { request: Request }) {
}

export async function loader({ request }: Route.LoaderArgs) {
// モック認証モードの場合
if (import.meta.env.VITE_USE_MOCK_AUTH === "true") {
// モックアカウントデータを返す
const mockAccounts = [
{
id: "mock-account-1",
name: "山田太郎",
email: "[email protected]",
photo: null,
organizationLine: "開発部 / エンジニアリング課",
residence: "東京都",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
{
id: "mock-account-2",
name: "佐藤花子",
email: "[email protected]",
photo: null,
organizationLine: "デザイン部 / UI/UX課",
residence: "大阪府",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
{
id: "mock-account-3",
name: "田中一郎",
email: "[email protected]",
photo: null,
organizationLine: "営業部 / 企画課",
residence: "愛知県",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
];

return { accounts: mockAccounts };
}

// 本番モード(Amplify認証)
const responseHeaders = new Headers();
return runWithAmplifyServerContext({
serverContext: { request, responseHeaders },
Expand Down
Loading