メインコンテンツまでスキップ
バージョン: design-archive

2.2. フロントエンド仕様

React (Vite) で構築されたシングルページアプリケーション (SPA)。ユーザーインターフェースの提供とバックエンドAPIとの通信を担います。

コンポーネント図​

コンポーネント説明
Pages各画面(ページ)を構成するコンポーネント。
Componentsボタンやナビゲーションバーなど、再利用可能なUI部品。
StoresZustandを使用してアプリケーション全体の状態を管理するストア。
ServicesAPIクライアントなど、外部との通信処理を責務とするモジュール。

画面一覧​

画面パス認証説明
HomePage/不要アプリケーションのトップページ。ログインや新規登録への導線。
LoginPage/login不要ログインフォーム画面。
RegisterPage/register不要新規ユーザー登録フォーム画面。
NetworkChatPage/chat必要グラフ可視化とチャットUIを統合したメイン画面。

状態管理とAPI連携 (Zustand & Axios)​

状態管理にはZustandを使用し、機能ごとにストアを分割します。API通信にはaxiosをベースとしたクライアント (services/api.js) を用い、各ストアのアクション内から呼び出します。APIクライアントは全てのリクエストに認証トークンを付与し、トークン失効時はログインページへリダイレクトします。

authStore​

ユーザーの認証状態とアクセストークンを管理します。

  • 状態: isAuthenticated, user, token
  • 主要なアクションと連携API:
    • login(username, password): POST /auth/token を呼び出し、成功時にトークンを状態とlocalStorageに保存する。
    • register(username, password): POST /auth/register を呼び出す。
    • logout(): トークンを削除し、状態をリセットする。

networkStore​

表示中のグラフデータやレイアウト情報を管理します。

  • 状態: networkId, nodes, edges, layout
  • 主要なアクションと連携API:
    • fetchNetwork(networkId): GET /network/{networkId}/visdata を呼び出し、取得したデータで nodes と edges を更新する。
    • uploadNetwork(file): POST /network/upload を呼び出す。
    • applyLayout(layoutName): POST /network/{networkId}/layout を呼び出す。

chatStore​

会話の履歴やメッセージ一覧を管理します。

  • 状態: conversationId, messages, isLoading
  • 主要なアクションと連携API:
    • fetchHistory(conversationId): GET /conversations/{id}/messages を呼び出し、messages 状態を更新する。
    • sendMessage(messageContent): POST /chat/process を呼び出し、UIのローディング状態を管理しつつ、返信メッセージとグラフの更新情報を受け取る。

コード例: sendMessage アクションの実装イメージ​

// chatStore.js (Zustand)
import { create } from 'zustand';
import { api } from '../services/api'; // axios instance
import { useNetworkStore } from './networkStore';

export const useChatStore = create((set, get) => ({
messages: [],
isLoading: false,
sendMessage: async (messageContent) => {
const conversationId = get().conversationId;
set({ isLoading: true });

try {
// ユーザーのメッセージをUIに即時反映
const userMessage = { role: 'user', content: messageContent };
set((state) => ({ messages: [...state.messages, userMessage] }));

// バックエンドに処理をリクエスト
const response = await api.post('/chat/process', {
conversation_id: conversationId,
message: userMessage,
});

// アシスタントの返信をUIに反映
const assistantMessage = response.data.message;
set((state) => ({ messages: [...state.messages, assistantMessage] }));

// グラフが更新された場合、networkStoreのアクションを呼び出す
if (response.data.graph_updated) {
useNetworkStore.getState().setNetworkData(response.data.new_vis_data);
}
} catch (error) {
console.error("Failed to send message:", error);
// エラー処理
} finally {
set({ isLoading: false });
}
},
}));