관리자 멤버 상세와 추가 화면 구현
This commit is contained in:
35
pages/admin/members/[id].vue
Normal file
35
pages/admin/members/[id].vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<script setup>
|
||||
definePageMeta({
|
||||
layout: 'admin'
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const memberId = computed(() => String(route.params.id || ''))
|
||||
|
||||
const { data: member, error } = await useFetch(() => `/admin/api/members/${memberId.value}`, {
|
||||
default: () => null
|
||||
})
|
||||
|
||||
/**
|
||||
* 저장된 회원 정보로 화면 상태를 갱신한다.
|
||||
* @param {Object} savedMember - 저장된 회원
|
||||
* @returns {void}
|
||||
*/
|
||||
const handleMemberSaved = (savedMember) => {
|
||||
member.value = savedMember
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AdminMemberForm
|
||||
v-if="member"
|
||||
:member="member"
|
||||
mode="edit"
|
||||
@saved="handleMemberSaved"
|
||||
/>
|
||||
<section v-else class="admin-member-detail bg-paper p-6">
|
||||
<div class="rounded-xl border border-line bg-white px-5 py-8 text-sm text-muted">
|
||||
{{ error?.data?.message || '회원 정보를 불러올 수 없습니다.' }}
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -29,6 +29,19 @@ const memberCountLabel = computed(() => {
|
||||
return `${count}명`
|
||||
})
|
||||
|
||||
/**
|
||||
* 회원 상세 화면으로 이동한다.
|
||||
* @param {Object} member - 회원 정보
|
||||
* @returns {Promise<void>} 이동 처리
|
||||
*/
|
||||
const navigateToMember = async (member) => {
|
||||
if (!member?.id) {
|
||||
return
|
||||
}
|
||||
|
||||
await navigateTo(`/admin/members/${member.id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원 이니셜을 반환한다.
|
||||
* @param {Object} member - 회원 정보
|
||||
@@ -100,9 +113,12 @@ const formatRelativeTime = (value) => {
|
||||
|
||||
<template>
|
||||
<section class="admin-members bg-paper p-6">
|
||||
<div class="admin-members__header flex flex-col gap-5 border-b border-line pb-6 xl:flex-row xl:items-center xl:justify-between">
|
||||
<div class="admin-members__header flex flex-col gap-5 pb-6 xl:flex-row xl:items-center xl:justify-between">
|
||||
<div>
|
||||
<h1 class="admin-members__title text-3xl font-semibold tracking-[-0.01em] text-[#15171a]">
|
||||
<p class="admin-members__eyebrow text-xs font-semibold uppercase text-muted">
|
||||
Members
|
||||
</p>
|
||||
<h1 class="admin-members__title mt-2 text-3xl font-semibold tracking-[-0.01em] text-[#15171a]">
|
||||
멤버
|
||||
</h1>
|
||||
</div>
|
||||
@@ -120,12 +136,12 @@ const formatRelativeTime = (value) => {
|
||||
aria-label="멤버 검색"
|
||||
>
|
||||
</label>
|
||||
<button
|
||||
class="admin-members__new h-11 rounded-md bg-[#15171a] px-4 text-sm font-semibold text-white transition hover:bg-[#2b2f35] focus-visible:outline focus-visible:ring-2 focus-visible:ring-[#8e9cac] focus-visible:ring-offset-2"
|
||||
type="button"
|
||||
<NuxtLink
|
||||
class="admin-members__new inline-flex h-11 items-center rounded-md bg-[#15171a] px-4 text-sm font-semibold text-white transition hover:bg-[#2b2f35] focus-visible:outline focus-visible:ring-2 focus-visible:ring-[#8e9cac] focus-visible:ring-offset-2"
|
||||
to="/admin/members/new"
|
||||
>
|
||||
멤버 추가
|
||||
</button>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -141,7 +157,14 @@ const formatRelativeTime = (value) => {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="admin-members__table-body divide-y divide-line/70 bg-paper">
|
||||
<tr v-for="member in filteredMembers" :key="member.id" class="admin-members__row align-middle transition-colors hover:bg-[#f7f8fa]">
|
||||
<tr
|
||||
v-for="member in filteredMembers"
|
||||
:key="member.id"
|
||||
class="admin-members__row cursor-pointer align-middle transition-colors hover:bg-[#f7f8fa] focus-within:bg-[#f7f8fa]"
|
||||
tabindex="0"
|
||||
@click="navigateToMember(member)"
|
||||
@keydown.enter.prevent="navigateToMember(member)"
|
||||
>
|
||||
<td class="admin-members__cell py-5 pr-5">
|
||||
<div class="admin-members__profile flex min-w-0 items-center gap-3">
|
||||
<img
|
||||
|
||||
22
pages/admin/members/new.vue
Normal file
22
pages/admin/members/new.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<script setup>
|
||||
definePageMeta({
|
||||
layout: 'admin'
|
||||
})
|
||||
|
||||
/**
|
||||
* 새 회원 저장 후 상세 화면으로 이동한다.
|
||||
* @param {Object} member - 저장된 회원
|
||||
* @returns {Promise<void>} 이동 처리
|
||||
*/
|
||||
const handleMemberSaved = async (member) => {
|
||||
if (!member?.id) {
|
||||
return
|
||||
}
|
||||
|
||||
await navigateTo(`/admin/members/${member.id}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AdminMemberForm mode="new" @saved="handleMemberSaved" />
|
||||
</template>
|
||||
Reference in New Issue
Block a user