feat: add MCP configuration and update login page design
Some checks failed
ci / ci (22, ubuntu-latest) (push) Failing after 26m43s
Some checks failed
ci / ci (22, ubuntu-latest) (push) Failing after 26m43s
- Introduced a new `.mcp.json` file for server configurations. - Updated `package.json` to include the `shadcn` dependency. - Modified `pnpm-lock.yaml` to reflect the new dependency. - Adjusted `.claude/settings.local.json` to disable specific MCP servers. - Enhanced the login page design in `login.vue` with improved layout and user experience elements.
This commit is contained in:
@@ -5,5 +5,11 @@
|
||||
"mcp__context7__query-docs",
|
||||
"Bash(npx nuxi@latest:*)"
|
||||
]
|
||||
}
|
||||
},
|
||||
"disabledMcpjsonServers": [
|
||||
"context7",
|
||||
"playwright",
|
||||
"sequential-thinking",
|
||||
"shadcn"
|
||||
]
|
||||
}
|
||||
|
||||
30
.mcp.json
Normal file
30
.mcp.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"context7": {
|
||||
"type": "http",
|
||||
"url": "https://mcp.context7.com/mcp"
|
||||
},
|
||||
"playwright": {
|
||||
"type": "stdio",
|
||||
"command": "cmd",
|
||||
"args": ["/c", "npx", "@playwright/mcp@latest"],
|
||||
"env": {}
|
||||
},
|
||||
"sequential-thinking": {
|
||||
"type": "stdio",
|
||||
"command": "cmd",
|
||||
"args": [
|
||||
"/c",
|
||||
"npx",
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-sequential-thinking"
|
||||
],
|
||||
"env": {}
|
||||
},
|
||||
"shadcn": {
|
||||
"type": "stdio",
|
||||
"command": "cmd",
|
||||
"args": ["/c", "npx", "shadcn@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +1,257 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: false })
|
||||
definePageMeta({ layout: false });
|
||||
|
||||
const supabase = useSupabaseClient()
|
||||
const email = ref('')
|
||||
const loading = ref(false)
|
||||
const message = ref('')
|
||||
const error = ref('')
|
||||
const supabase = useSupabaseClient();
|
||||
const email = ref("");
|
||||
const loading = ref(false);
|
||||
const message = ref("");
|
||||
const error = ref("");
|
||||
|
||||
async function sendMagicLink() {
|
||||
if (!email.value) return
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
message.value = ''
|
||||
if (!email.value) return;
|
||||
loading.value = true;
|
||||
error.value = "";
|
||||
message.value = "";
|
||||
|
||||
const { error: err } = await supabase.auth.signInWithOtp({
|
||||
email: email.value,
|
||||
options: {
|
||||
emailRedirectTo: `${window.location.origin}/confirm`
|
||||
}
|
||||
})
|
||||
emailRedirectTo: `${window.location.origin}/confirm`,
|
||||
},
|
||||
});
|
||||
|
||||
loading.value = false
|
||||
loading.value = false;
|
||||
if (err) {
|
||||
error.value = err.message
|
||||
error.value = err.message;
|
||||
} else {
|
||||
message.value = `${email.value}로 로그인 링크를 전송했습니다. 이메일을 확인해주세요.`
|
||||
message.value = `${email.value}로 로그인 링크를 전송했습니다. 이메일을 확인해주세요.`;
|
||||
}
|
||||
}
|
||||
|
||||
async function signInWithGoogle() {
|
||||
await supabase.auth.signInWithOAuth({
|
||||
provider: 'google',
|
||||
provider: "google",
|
||||
options: {
|
||||
redirectTo: `${window.location.origin}/confirm`
|
||||
}
|
||||
})
|
||||
redirectTo: `${window.location.origin}/confirm`,
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UApp>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-green-50 to-emerald-100 dark:from-gray-900 dark:to-gray-800 p-4">
|
||||
<UCard class="w-full max-w-md">
|
||||
<!-- Logo -->
|
||||
<template #header>
|
||||
<div class="text-center py-4">
|
||||
<div class="flex items-center justify-center gap-2 mb-2">
|
||||
<UIcon name="i-lucide-tent" class="text-4xl text-primary-500" />
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">CampGear</h1>
|
||||
<div class="min-h-screen flex">
|
||||
<!-- 좌측 브랜딩 패널 (데스크탑에서만 표시) -->
|
||||
<div
|
||||
class="hidden lg:flex lg:w-1/2 relative overflow-hidden bg-gradient-to-br from-green-500 via-emerald-600 to-green-800 flex-col justify-between p-12"
|
||||
>
|
||||
<!-- 배경 패턴 -->
|
||||
<div class="absolute inset-0 opacity-10">
|
||||
<div
|
||||
class="absolute top-0 left-0 w-64 h-64 rounded-full bg-white -translate-x-1/2 -translate-y-1/2"
|
||||
/>
|
||||
<div
|
||||
class="absolute bottom-0 right-0 w-96 h-96 rounded-full bg-white translate-x-1/3 translate-y-1/3"
|
||||
/>
|
||||
<div
|
||||
class="absolute top-1/2 left-1/2 w-48 h-48 rounded-full bg-white -translate-x-1/2 -translate-y-1/2"
|
||||
/>
|
||||
</div>
|
||||
<p class="text-gray-500 dark:text-gray-400">캠핑 장비 관리 앱</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="space-y-4 py-2">
|
||||
<!-- Magic Link -->
|
||||
<!-- 로고 -->
|
||||
<div class="relative z-10 flex items-center gap-3">
|
||||
<div
|
||||
class="w-10 h-10 rounded-xl bg-white/20 backdrop-blur flex items-center justify-center"
|
||||
>
|
||||
<UIcon name="i-lucide-tent" class="text-white text-xl" />
|
||||
</div>
|
||||
<span class="text-white text-xl font-bold tracking-tight"
|
||||
>CampGear</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- 메인 카피 -->
|
||||
<div class="relative z-10 space-y-6">
|
||||
<div class="space-y-3">
|
||||
<UFormField label="이메일" name="email">
|
||||
<h2 class="text-4xl font-bold text-white leading-tight">
|
||||
캠핑의 모든 것,<br />한 곳에서 관리하세요
|
||||
</h2>
|
||||
<p class="text-green-100 text-lg leading-relaxed">
|
||||
장비 구매부터 중고 거래까지,<br />스마트한 캠핑 장비 관리를
|
||||
경험하세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 기능 목록 -->
|
||||
<div class="space-y-3">
|
||||
<div
|
||||
v-for="feature in [
|
||||
{ icon: 'i-lucide-package', text: '장비 구매 내역 관리' },
|
||||
{ icon: 'i-lucide-repeat', text: '중고 장비 판매 · 추적' },
|
||||
{ icon: 'i-lucide-bot', text: 'AI 캠핑 어시스턴트' },
|
||||
]"
|
||||
:key="feature.text"
|
||||
class="flex items-center gap-3"
|
||||
>
|
||||
<div
|
||||
class="w-8 h-8 rounded-lg bg-white/20 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<UIcon :name="feature.icon" class="text-white text-sm" />
|
||||
</div>
|
||||
<span class="text-green-50 text-sm font-medium">{{
|
||||
feature.text
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 하단 문구 -->
|
||||
<div class="relative z-10">
|
||||
<p class="text-green-200 text-sm">
|
||||
© 2026 CampGear. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 우측 로그인 폼 -->
|
||||
<div
|
||||
class="flex-1 flex items-center justify-center p-6 sm:p-12 bg-white dark:bg-gray-950"
|
||||
>
|
||||
<div class="w-full max-w-sm space-y-8">
|
||||
<!-- 모바일용 로고 -->
|
||||
<div class="lg:hidden text-center space-y-2">
|
||||
<div
|
||||
class="inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-green-500 mb-2"
|
||||
>
|
||||
<UIcon name="i-lucide-tent" class="text-white text-2xl" />
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
CampGear
|
||||
</h1>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
캠핑 장비 관리 앱
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 폼 헤더 -->
|
||||
<div class="space-y-1">
|
||||
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
로그인
|
||||
</h2>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
계속하려면 이메일을 입력하거나 Google 계정으로 로그인하세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 로그인 폼 -->
|
||||
<div class="space-y-4">
|
||||
<!-- Google 로그인 -->
|
||||
<UButton
|
||||
color="neutral"
|
||||
variant="outline"
|
||||
class="w-full"
|
||||
size="lg"
|
||||
@click="signInWithGoogle"
|
||||
>
|
||||
<template #leading>
|
||||
<UIcon name="i-simple-icons-google" class="text-base" />
|
||||
</template>
|
||||
Google로 계속하기
|
||||
</UButton>
|
||||
|
||||
<!-- 구분선 -->
|
||||
<div class="relative flex items-center gap-3">
|
||||
<div class="flex-1 h-px bg-gray-200 dark:bg-gray-800" />
|
||||
<span class="text-xs text-gray-400 dark:text-gray-500 font-medium"
|
||||
>또는 이메일로</span
|
||||
>
|
||||
<div class="flex-1 h-px bg-gray-200 dark:bg-gray-800" />
|
||||
</div>
|
||||
|
||||
<!-- 이메일 입력 -->
|
||||
<div class="space-y-3">
|
||||
<UFormField name="email">
|
||||
<UInput
|
||||
v-model="email"
|
||||
type="email"
|
||||
placeholder="your@email.com"
|
||||
size="lg"
|
||||
class="w-full"
|
||||
:ui="{ base: 'w-full' }"
|
||||
@keyup.enter="sendMagicLink"
|
||||
/>
|
||||
>
|
||||
<template #leading>
|
||||
<UIcon name="i-lucide-mail" class="text-gray-400" />
|
||||
</template>
|
||||
</UInput>
|
||||
</UFormField>
|
||||
|
||||
<UButton
|
||||
label="매직 링크로 로그인"
|
||||
icon="i-lucide-mail"
|
||||
color="primary"
|
||||
class="w-full"
|
||||
size="lg"
|
||||
:loading="loading"
|
||||
@click="sendMagicLink"
|
||||
>
|
||||
<template #leading>
|
||||
<UIcon
|
||||
v-if="!loading"
|
||||
name="i-lucide-send"
|
||||
class="text-base"
|
||||
/>
|
||||
</template>
|
||||
매직 링크 전송
|
||||
</UButton>
|
||||
</div>
|
||||
|
||||
<!-- Divider -->
|
||||
<USeparator label="또는" />
|
||||
|
||||
<!-- Google OAuth -->
|
||||
<UButton
|
||||
label="Google로 로그인"
|
||||
icon="i-simple-icons-google"
|
||||
color="neutral"
|
||||
variant="outline"
|
||||
class="w-full"
|
||||
@click="signInWithGoogle"
|
||||
/>
|
||||
|
||||
<!-- Feedback -->
|
||||
<!-- 피드백 메시지 -->
|
||||
<Transition
|
||||
enter-active-class="transition duration-300 ease-out"
|
||||
enter-from-class="opacity-0 -translate-y-2"
|
||||
enter-to-class="opacity-100 translate-y-0"
|
||||
>
|
||||
<UAlert
|
||||
v-if="message"
|
||||
color="success"
|
||||
icon="i-lucide-check-circle"
|
||||
:description="message"
|
||||
class="mt-2"
|
||||
/>
|
||||
</Transition>
|
||||
<Transition
|
||||
enter-active-class="transition duration-300 ease-out"
|
||||
enter-from-class="opacity-0 -translate-y-2"
|
||||
enter-to-class="opacity-100 translate-y-0"
|
||||
>
|
||||
<UAlert
|
||||
v-if="error"
|
||||
color="error"
|
||||
icon="i-lucide-alert-circle"
|
||||
:description="error"
|
||||
class="mt-2"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
<!-- 안내 문구 -->
|
||||
<p
|
||||
class="text-center text-xs text-gray-400 dark:text-gray-500 leading-relaxed"
|
||||
>
|
||||
로그인 시 CampGear의
|
||||
<a
|
||||
href="#"
|
||||
class="text-green-600 dark:text-green-400 hover:underline"
|
||||
>이용약관</a
|
||||
>
|
||||
및
|
||||
<a
|
||||
href="#"
|
||||
class="text-green-600 dark:text-green-400 hover:underline"
|
||||
>개인정보처리방침</a
|
||||
>에 동의하게 됩니다.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
</div>
|
||||
</UApp>
|
||||
</template>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"@nuxt/eslint": "^1.15.2",
|
||||
"@types/node": "^22.13.10",
|
||||
"eslint": "^10.0.2",
|
||||
"shadcn": "^4.0.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vue-tsc": "^3.2.5"
|
||||
},
|
||||
|
||||
1411
pnpm-lock.yaml
generated
1411
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user