構成メモ（個人用）

# Vue 3 × モックAPI × 環境変数制御：未納エラーの表示処理テスト構成メモ

## 📝 概要

業務で担当中の Vue 3 アプリにて、**未納エラーをUI上で表示し、「次へ」ボタンを非活性にする処理**の実装メモ。
APIはモック（`mock-test-api.ts`）で、将来的な切り替えに備えつつ、現時点では環境変数経由でモックAPI関数を指定している。
自分用メモで他人には非公開の想定。

---

## 🗂 現状の構成ファイル

```
src/
├── mock-test-api.ts         // モックAPI定義（isNotPaid返す）
├── FrontRepository-test.ts  // API呼び出し用リポジトリ
├── BusinessLogic-test.ts    // ビジネスロジック：UI状態計算
├── Front-test.vue           // UI本体（未納エラー表示・ボタン制御）
├── vite-env.d.ts            // import.meta.env の型定義
.env                         // 環境変数定義（関数名管理）
```

---

## ✅ 使用する環境変数

```env
VITE_API_FUNCTION_NAME=fetchMockStatus
```

---

## 📄 vite-env.d.ts

```ts
interface ImportMetaEnv {
  readonly VITE_API_FUNCTION_NAME: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}
```

---

## 🔧 モックAPI（mock-test-api.ts）

```ts
export function fetchMockStatus(scenario: 'scenarioA' | 'scenarioB' = 'scenarioA') {
  let isNotPaid = false;
  if (scenario === 'scenarioA') {
    isNotPaid = true;
  }
  return Promise.resolve({ isNotPaid });
}
```

---

## 🔁 リポジトリ（FrontRepository-test.ts）

```ts
import * as mockApi from './mock-test-api';

const apiFunctionName = import.meta.env.VITE_API_FUNCTION_NAME || 'fetchMockStatus';

export async function getFrontStatus(scenario: 'scenarioA' | 'scenarioB' = 'scenarioA') {
  const fetchFunc = mockApi[apiFunctionName];
  if (typeof fetchFunc !== 'function') {
    throw new Error(`API関数 "${apiFunctionName}" が見つかりません`);
  }
  return await fetchFunc(scenario);
}
```

---

## 📐 ビジネスロジック（BusinessLogic-test.ts）

```ts
export function getUiState({ isNotPaid, miniFlag = false }) {
  const showErrorPanel = isNotPaid || miniFlag;
  return {
    showErrorPanel,
    nextDisabled: showErrorPanel,
    backDisabled: false,
  };
}
```

---

## 🖥 UIコンポーネント（Front-test.vue）

```vue
<template>
  <div style="max-width: 400px; margin: 2rem auto; padding: 2rem; border: 1px solid #ccc; border-radius: 8px;">
    <h2>テストUI</h2>

    <div>
      <label><input type="radio" value="scenarioA" v-model="scenario" /> シナリオA: 未納あり</label>
      <label style="margin-left: 1rem;"><input type="radio" value="scenarioB" v-model="scenario" /> シナリオB: 未納なし</label>
    </div>

    <div>
      <label><input type="checkbox" v-model="miniFlag" /> miniFlag: 仮会員</label>
    </div>

    <button @click="fetchStatus">状態取得</button>

    <div v-if="uiState.showErrorPanel" style="background: #ffe0e0; padding: 1rem; margin-top: 1rem;">
      <div v-if="uiState.isNotPaid">未納エラー</div>
      <div v-if="uiState.miniFlag">ミニフラグエラー</div>
    </div>

    <div style="margin-top: 1rem;">
      <button :disabled="uiState.nextDisabled">次へ</button>
      <button :disabled="uiState.backDisabled">戻る</button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { getFrontStatus } from './FrontRepository-test';
import { getUiState } from './BusinessLogic-test';

const scenario = ref('scenarioA');
const miniFlag = ref(false);

const uiState = ref({
  showErrorPanel: false,
  nextDisabled: false,
  backDisabled: false,
  isNotPaid: false,
  miniFlag: false
});

async function fetchStatus() {
  const res = await getFrontStatus(scenario.value);
  uiState.value = {
    ...getUiState({ isNotPaid: res.isNotPaid, miniFlag: miniFlag.value }),
    isNotPaid: res.isNotPaid,
    miniFlag: miniFlag.value
  };
}
fetchStatus();
</script>
```

---

## 🛠 実装時の進め方メモ（個人向け）

### 🎯 状況

* mock-test-api.ts と FrontRepository-test.ts は既に用意されていた
* UI・ボタン制御は未実装
* miniFlag の設定はフロントロジック側で管理してよい

---

### ✅ 実装順メモ

| 順番 | 作業                                              | ファイル                    |
| -- | ----------------------------------------------- | ----------------------- |
| ①  | `getUiState()` を作成（isNotPaid / miniFlag → UI状態） | `BusinessLogic-test.ts` |
| ②  | Vue内に `uiState` を定義、取得した状態を格納                   | `Front-test.vue`        |
| ③  | UIテンプレートにエラーパネルとボタン状態を反映                        | `Front-test.vue`        |
| ④  | `getFrontStatus()` を使って状態を取得＆更新                 | `Front-test.vue`        |
| ⑤  | 初期表示時にも `fetchStatus()` を実行して状態反映               | `Front-test.vue`        |

---

## 📌 注意点メモ

* **モックAPIがリポジトリをimportするのはNG設計**（依存逆転）
* **環境変数経由で関数名を指定する設計**は、将来の切り替えに柔軟で◎
* **ロジックとUIは分離**（getUiStateでUI状態だけ渡す）