36 lines
1.6 KiB
Vue
36 lines
1.6 KiB
Vue
<script setup lang="ts">
|
|
import type { KbxUserNotification } from '@kbx/contracts'
|
|
|
|
defineProps<{ notifications: KbxUserNotification[] }>()
|
|
const emit = defineEmits<{ open: [KbxUserNotification]; read: [string] }>()
|
|
</script>
|
|
|
|
<template>
|
|
<section class="kbx-notification-center" aria-label="알림 센터">
|
|
<button
|
|
v-for="item in notifications"
|
|
:key="item.id"
|
|
type="button"
|
|
class="notice"
|
|
:class="[`is-${item.severity}`, { unread: !item.readAt }]"
|
|
@click="emit('open', item); emit('read', item.id)"
|
|
>
|
|
<span class="marker" aria-hidden="true" />
|
|
<span class="copy"><strong>{{ item.title }}</strong><small v-if="item.message">{{ item.message }}</small></span>
|
|
<time>{{ new Date(item.createdAt).toLocaleString('ko-KR') }}</time>
|
|
</button>
|
|
<p v-if="notifications.length === 0" class="empty">새 알림이 없습니다.</p>
|
|
</section>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.kbx-notification-center { display:grid; gap:4px; }
|
|
.notice { display:grid; grid-template-columns:8px 1fr auto; align-items:start; gap:8px; padding:10px; border:1px solid transparent; background:transparent; text-align:left; cursor:pointer; }
|
|
.notice:hover { background:var(--kbx-color-surface-hover); }
|
|
.marker { width:6px; height:6px; margin-top:6px; border-radius:50%; background:var(--kbx-color-text-muted); }
|
|
.unread .marker { background:var(--kbx-color-primary); }
|
|
.copy { display:grid; gap:2px; } small,time,.empty { color:var(--kbx-color-text-muted); font-size:var(--kbx-font-xs); }
|
|
time { white-space:nowrap; }
|
|
.empty { margin:0; padding:12px; }
|
|
</style>
|