🦁

Nuxt.jsでWebアプリケーション開発メモ3

に公開

概要

  • ログイン処理の実装。
  • 基本的にClaude Codeに実装を任せる。

前提条件

  • バックエンドはPython(Django)のrest_frameworkで作成。
    • ユーザーモデル、ユーザーの一覧、追加、変更、削除API実装済み。
    • ログイン、ログアウトAPI実装済み。
    • JWT認証を使用。
    • 管理ユーザー追加済み。(admin)
  • DBは暫定でSqlite3を使用。

プロンプト3

# 命令3
login.vueにLOG INボタンをクリックしたときのログイン処理を実装してください。
- ログインはバックエンドのloginAPIを実行します。
- APIのパスは http://localhost:8000/api/auth/login/ です。
- JWT認証を使っていますのでレスポンスを適宜保存してください。
- ログインが成功したらひとまずTOPページに遷移しますので、top.vueを追加してそのページに遷移するようにしてください。
- TOPページは暫定で ```Welcome Prototype SPA``` の表示のみでOK。
- ログインに失敗した場合は、LOGINボタンの下にエラーメッセージを表示するようにしてください。

実装されたソースコード

app/pages/login.vue
@@ -22,9 +22,17 @@
        <!-- Login Link -->
        <div class="flex justify-center pt-4">
          <button
            @click="handleLogin"
+           :disabled="isLoading"
-           class="text-blue-500 hover:text-blue-600 font-medium text-sm underline-offset-4 hover:underline"
+           class="text-blue-500 hover:text-blue-600 font-medium text-sm underline-offset-4 hover:underline 
disabled:opacity-50"
          >
-           LOG IN
+           {{ isLoading ? 'LOGGING IN...' : 'LOG IN' }}
          </button>
        </div>
+
+       <!-- Error Message -->
+       <div v-if="errorMessage" class="text-red-500 text-sm text-center mt-4">
+         {{ errorMessage }}
+       </div>
      </div>
    </div>
 </template>
@@ -35,8 +43,50 @@
 <script setup lang="ts">
 const username = ref('')
 const password = ref('')
+const isLoading = ref(false)
+const errorMessage = ref('')

-const handleLogin = () => {
-  // ログイン処理を実装予定
-  console.log('Login clicked', { username: username.value, password: password.value })
+const handleLogin = async () => {
+  if (!username.value || !password.value) {
+    errorMessage.value = 'ユーザー名とパスワードを入力してください'
+    return
+  }
+
+  isLoading.value = true
+  errorMessage.value = ''
+
+  try {
+    const response = await $fetch('http://localhost:8000/api/auth/login/', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: {
+        username: username.value,
+        password: password.value,
+      }
+    })
+
+    if (response.access) {
+      localStorage.setItem('access_token', response.access)
+      if (response.refresh) {
+        localStorage.setItem('refresh_token', response.refresh)
+      }
+      
+      await navigateTo('/top')
+    } else {
+      errorMessage.value = 'ログイン処理でエラーが発生しました。管理者にお問い合わせください。'
+    }
+  } catch (error: any) {
+    console.error('Login error:', error)
+    if (error.data?.detail) {
+      errorMessage.value = error.data.detail
+    } else if (error.data?.non_field_errors) {
+      errorMessage.value = error.data.non_field_errors[0]
+    } else {
+      errorMessage.value = 'ログインに失敗しました。再度お試しください。'
+    }
+  } finally {
+    isLoading.value = false
+  }
 }
 </script>
app/pages/top.vue
<template>
  <div class="flex items-center justify-center pt-16">
    <div class="text-center">
      <h1 class="text-2xl font-bold text-gray-800">
        Welcome Prototype SPA
      </h1>
    </div>
  </div>
</template>

<script setup lang="ts">
</script>

ソースコード差分

https://github.com/tkure/prototype-frontend/commit/525be1fb228e6b6a76b1d802fb0c0fef55e04a0b


→ Nuxt.jsでWebアプリケーション開発メモ4

Discussion