🦁
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>
ソースコード差分
Discussion