275 lines
12 KiB
Vue
275 lines
12 KiB
Vue
<script setup>
|
|
import {
|
|
DEFAULT_FEATURED_POST_LIMIT,
|
|
DEFAULT_HOME_LATEST_POST_LIMIT,
|
|
DEFAULT_PAGE_SECTION_ITEM_LIMIT,
|
|
DEFAULT_POST_LIST_PAGE_SIZE,
|
|
DEFAULT_TAG_POST_LIST_PAGE_SIZE,
|
|
normalizeDisplayCount
|
|
} from '~/lib/display-count-settings.js'
|
|
import {
|
|
DEFAULT_POST_TAG_LIMIT,
|
|
MAX_POST_TAG_LIMIT,
|
|
MIN_POST_TAG_LIMIT,
|
|
normalizePostTagLimit
|
|
} from '~/lib/post-tag-limit.js'
|
|
import {
|
|
formatUploadSizeLimit,
|
|
normalizeUploadMaxFileCount,
|
|
normalizeUploadMaxTotalSize
|
|
} from '~/lib/upload-size-limit.js'
|
|
|
|
/**
|
|
* POST 설정 카드
|
|
* @property {Object} form - 사이트 설정 폼 객체
|
|
* @property {boolean} editing - 편집 모드 여부
|
|
* @property {boolean} saving - 저장 중 여부
|
|
* @property {boolean} hasChanges - 변경 여부
|
|
* @property {Array<{ value: number, label: string }>} postListCountOptions - 게시물 목록 표시개수 선택지
|
|
* @property {Array<{ value: number, label: string }>} displayCountOptions - 일반 표시개수 선택지
|
|
*/
|
|
defineProps({
|
|
form: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
editing: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
saving: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
hasChanges: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
postListCountOptions: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
displayCountOptions: {
|
|
type: Array,
|
|
default: () => []
|
|
}
|
|
})
|
|
|
|
defineEmits(['begin', 'cancel', 'save'])
|
|
</script>
|
|
|
|
<template>
|
|
<section
|
|
id="admin-settings-section-post"
|
|
class="admin-post-settings-card admin-settings-screen__card admin-settings-screen__card--post relative flex flex-col gap-6 rounded-xl border border-[#d8dce1] bg-white p-5 transition-all hover:border-[#c5cbd3] hover:shadow-sm md:p-7"
|
|
>
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div class="min-w-0 flex-1">
|
|
<h2 class="text-base font-semibold text-[#15171a] md:text-lg">
|
|
POST 설정
|
|
</h2>
|
|
<p
|
|
v-if="!editing"
|
|
class="mr-5 mt-1 text-pretty text-sm leading-relaxed text-[#657080]"
|
|
>
|
|
공개 글 상세·관리자 글 목록에서 발행 후 수정이 있었을 때 수정일을 함께 표시합니다.
|
|
글쓰기 태그 제한과 공개 목록 표시개수도 함께 관리합니다.
|
|
</p>
|
|
</div>
|
|
<div class="-mr-1 mt-[-5px] flex shrink-0 items-center justify-start gap-2">
|
|
<template v-if="!editing">
|
|
<button
|
|
class="inline-flex h-7 cursor-pointer items-center justify-center rounded px-3 text-sm font-semibold whitespace-nowrap text-[#15171a] transition hover:bg-[#eceff2] hover:text-black"
|
|
type="button"
|
|
@click="$emit('begin')"
|
|
>
|
|
편집
|
|
</button>
|
|
</template>
|
|
<template v-else>
|
|
<button
|
|
class="inline-flex h-7 cursor-pointer items-center justify-center rounded px-3 text-sm font-semibold whitespace-nowrap text-[#5d6673] transition hover:bg-[#eceff2] hover:text-[#15171a]"
|
|
type="button"
|
|
:disabled="saving"
|
|
@click="$emit('cancel')"
|
|
>
|
|
취소
|
|
</button>
|
|
<button
|
|
class="inline-flex h-7 cursor-pointer items-center justify-center rounded px-3 text-sm font-semibold whitespace-nowrap text-[#15171a] transition hover:bg-[#eceff2] hover:text-black disabled:opacity-50"
|
|
type="button"
|
|
:disabled="saving || !hasChanges"
|
|
@click="$emit('save')"
|
|
>
|
|
{{ saving ? '저장 중' : '저장' }}
|
|
</button>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
v-if="!editing"
|
|
class="admin-post-settings-card__readonly admin-settings-screen__post-readonly border-t border-[#eceff2] pt-5 text-sm"
|
|
>
|
|
<div class="admin-settings-screen__post-toggle flex items-center justify-between gap-4">
|
|
<span class="font-bold text-[#15171a]">수정일 표시</span>
|
|
<span class="admin-settings-screen__post-toggle-control relative inline-flex h-7 w-12 shrink-0 cursor-not-allowed items-center opacity-55 grayscale" aria-disabled="true">
|
|
<input
|
|
:checked="form.showPostUpdatedAt"
|
|
class="peer sr-only"
|
|
type="checkbox"
|
|
disabled
|
|
aria-label="수정일 표시"
|
|
>
|
|
<span class="absolute inset-0 rounded-full bg-[#c8ced3] transition-colors peer-checked:bg-[#6d747d]" aria-hidden="true" />
|
|
<span class="relative ml-1 size-5 rounded-full bg-[#f4f6f8] shadow transition-transform peer-checked:translate-x-5" aria-hidden="true" />
|
|
</span>
|
|
</div>
|
|
<div class="mt-5 flex items-center justify-between gap-4 border-t border-[#eceff2] pt-5">
|
|
<span class="font-bold text-[#15171a]">태그 최대 개수</span>
|
|
<span class="font-mono text-sm font-semibold text-[#657080]">
|
|
{{ normalizePostTagLimit(form.postTagLimit) }}개
|
|
</span>
|
|
</div>
|
|
<div class="mt-5 grid gap-3 border-t border-[#eceff2] pt-5">
|
|
<div class="flex items-center justify-between gap-4">
|
|
<span class="font-bold text-[#15171a]">표시개수 설정</span>
|
|
<span class="text-xs text-[#657080]">공개 목록 기준</span>
|
|
</div>
|
|
<div class="grid gap-2 text-xs text-[#657080] sm:grid-cols-2">
|
|
<div class="flex items-center justify-between gap-3 rounded-md border border-[#edf0f2] px-3 py-2">
|
|
<span>Latest</span>
|
|
<strong class="font-mono text-[#15171a]">{{ normalizeDisplayCount(form.homeLatestPostLimit, DEFAULT_HOME_LATEST_POST_LIMIT) }}개</strong>
|
|
</div>
|
|
<div class="flex items-center justify-between gap-3 rounded-md border border-[#edf0f2] px-3 py-2">
|
|
<span>Posts</span>
|
|
<strong class="font-mono text-[#15171a]">{{ normalizeDisplayCount(form.postListPageSize, DEFAULT_POST_LIST_PAGE_SIZE) }}개</strong>
|
|
</div>
|
|
<div class="flex items-center justify-between gap-3 rounded-md border border-[#edf0f2] px-3 py-2">
|
|
<span>태그 게시물</span>
|
|
<strong class="font-mono text-[#15171a]">{{ normalizeDisplayCount(form.tagPostListPageSize, DEFAULT_TAG_POST_LIST_PAGE_SIZE) }}개</strong>
|
|
</div>
|
|
<div class="flex items-center justify-between gap-3 rounded-md border border-[#edf0f2] px-3 py-2">
|
|
<span>Featured</span>
|
|
<strong class="font-mono text-[#15171a]">{{ normalizeDisplayCount(form.featuredPostLimit, DEFAULT_FEATURED_POST_LIMIT) }}개</strong>
|
|
</div>
|
|
<div class="flex items-center justify-between gap-3 rounded-md border border-[#edf0f2] px-3 py-2 sm:col-span-2">
|
|
<span>Pages 섹션</span>
|
|
<strong class="font-mono text-[#15171a]">{{ normalizeDisplayCount(form.pageSectionItemLimit, DEFAULT_PAGE_SECTION_ITEM_LIMIT) }}개</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-5 grid gap-3 border-t border-[#eceff2] pt-5">
|
|
<div class="flex items-center justify-between gap-4">
|
|
<span class="font-bold text-[#15171a]">업로드 제한</span>
|
|
<span class="text-xs text-[#657080]">1회 업로드 기준</span>
|
|
</div>
|
|
<div class="grid gap-2 text-xs text-[#657080] sm:grid-cols-2">
|
|
<div class="flex items-center justify-between gap-3 rounded-md border border-[#edf0f2] px-3 py-2">
|
|
<span>파일 수</span>
|
|
<strong class="font-mono text-[#15171a]">{{ normalizeUploadMaxFileCount(form.uploadMaxFileCount) }}개</strong>
|
|
</div>
|
|
<div class="flex items-center justify-between gap-3 rounded-md border border-[#edf0f2] px-3 py-2">
|
|
<span>전체 용량</span>
|
|
<strong class="font-mono text-[#15171a]">{{ formatUploadSizeLimit(normalizeUploadMaxTotalSize(form.uploadMaxTotalSize)) }}</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
v-else
|
|
class="admin-post-settings-card__edit grid gap-5 border-t border-[#eceff2] pt-5 text-sm"
|
|
>
|
|
<label class="admin-settings-screen__post-toggle flex items-center justify-between gap-4">
|
|
<span class="font-bold text-[#15171a]">수정일 표시</span>
|
|
<span class="admin-settings-screen__post-toggle-control relative inline-flex h-7 w-12 shrink-0 items-center">
|
|
<input
|
|
v-model="form.showPostUpdatedAt"
|
|
class="peer sr-only"
|
|
type="checkbox"
|
|
aria-label="수정일 표시"
|
|
>
|
|
<span class="absolute inset-0 rounded-full bg-[#c8ced3] transition-colors peer-checked:bg-[#15171a]" aria-hidden="true" />
|
|
<span class="relative ml-1 size-5 rounded-full bg-white shadow transition-transform peer-checked:translate-x-5" aria-hidden="true" />
|
|
</span>
|
|
</label>
|
|
<label class="admin-settings-screen__field grid gap-2">
|
|
<span class="font-bold text-[#15171a]">태그 최대 개수</span>
|
|
<input
|
|
v-model.number="form.postTagLimit"
|
|
class="h-10 rounded-md border border-[#dce0e5] bg-white px-3 text-[#15171a] outline-none focus:border-[#15171a] focus:ring-1 focus:ring-[#15171a]"
|
|
type="number"
|
|
:min="MIN_POST_TAG_LIMIT"
|
|
:max="MAX_POST_TAG_LIMIT"
|
|
step="1"
|
|
@blur="form.postTagLimit = normalizePostTagLimit(form.postTagLimit)"
|
|
>
|
|
<span class="text-xs leading-relaxed text-[#657080]">
|
|
최소 {{ MIN_POST_TAG_LIMIT }}개, 최대 {{ MAX_POST_TAG_LIMIT }}개까지 설정할 수 있습니다. 기본값은 {{ DEFAULT_POST_TAG_LIMIT }}개입니다.
|
|
</span>
|
|
</label>
|
|
<div class="admin-settings-screen__field grid gap-3 border-t border-[#eceff2] pt-5">
|
|
<div>
|
|
<span class="font-bold text-[#15171a]">표시개수 설정</span>
|
|
<p class="mt-1 text-xs leading-relaxed text-[#657080]">
|
|
공개 목록에서 한 번에 불러오고 보여줄 개수를 선택합니다.
|
|
</p>
|
|
</div>
|
|
<div class="grid gap-3 sm:grid-cols-2">
|
|
<div class="grid gap-1.5">
|
|
<span class="text-xs font-semibold text-[#657080]">Latest</span>
|
|
<AdminSelectInput
|
|
v-model="form.homeLatestPostLimit"
|
|
:options="postListCountOptions"
|
|
label="Latest 표시개수"
|
|
select-class="admin-settings-screen__select h-10 rounded-md border-[#dce0e5] text-[#15171a] focus:ring-1 focus:ring-[#15171a]"
|
|
width-class="w-full"
|
|
/>
|
|
</div>
|
|
<div class="grid gap-1.5">
|
|
<span class="text-xs font-semibold text-[#657080]">Posts</span>
|
|
<AdminSelectInput
|
|
v-model="form.postListPageSize"
|
|
:options="postListCountOptions"
|
|
label="Posts 표시개수"
|
|
select-class="admin-settings-screen__select h-10 rounded-md border-[#dce0e5] text-[#15171a] focus:ring-1 focus:ring-[#15171a]"
|
|
width-class="w-full"
|
|
/>
|
|
</div>
|
|
<div class="grid gap-1.5">
|
|
<span class="text-xs font-semibold text-[#657080]">태그 게시물</span>
|
|
<AdminSelectInput
|
|
v-model="form.tagPostListPageSize"
|
|
:options="postListCountOptions"
|
|
label="태그 게시물 표시개수"
|
|
select-class="admin-settings-screen__select h-10 rounded-md border-[#dce0e5] text-[#15171a] focus:ring-1 focus:ring-[#15171a]"
|
|
width-class="w-full"
|
|
/>
|
|
</div>
|
|
<div class="grid gap-1.5">
|
|
<span class="text-xs font-semibold text-[#657080]">Featured</span>
|
|
<AdminSelectInput
|
|
v-model="form.featuredPostLimit"
|
|
:options="displayCountOptions"
|
|
label="Featured 표시개수"
|
|
select-class="admin-settings-screen__select h-10 rounded-md border-[#dce0e5] text-[#15171a] focus:ring-1 focus:ring-[#15171a]"
|
|
width-class="w-full"
|
|
/>
|
|
</div>
|
|
<div class="grid gap-1.5 sm:col-span-2">
|
|
<span class="text-xs font-semibold text-[#657080]">Pages 섹션</span>
|
|
<AdminSelectInput
|
|
v-model="form.pageSectionItemLimit"
|
|
:options="displayCountOptions"
|
|
label="Pages 섹션 표시개수"
|
|
select-class="admin-settings-screen__select h-10 rounded-md border-[#dce0e5] text-[#15171a] focus:ring-1 focus:ring-[#15171a]"
|
|
width-class="w-full"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|