feat: Implement session management and routing for general creation

- Added session initialization in main.ts to manage user sessions.
- Updated router to include a new route for joining or creating a general.
- Enhanced session store with methods for managing session tokens and user profiles.
- Introduced new components for displaying city, general, nation, and command information.
- Implemented loading states and error handling in the main view.
- Created a skeleton loader component for better user experience during data fetching.
- Updated TypeScript definitions for route metadata to include new authentication requirements.
This commit is contained in:
2026-01-16 15:57:56 +00:00
parent 15625f2c28
commit f8159728ca
20 changed files with 1342 additions and 18 deletions
@@ -0,0 +1,99 @@
<script setup lang="ts">
import SkeletonLines from '../ui/SkeletonLines.vue';
interface GeneralStats {
leadership: number;
strength: number;
intelligence: number;
}
interface GeneralInfo {
id: number;
name: string;
npcState: number;
officerLevel: number;
stats: GeneralStats;
gold: number;
rice: number;
crew: number;
train: number;
atmos: number;
injury: number;
experience: number;
dedication: number;
}
const props = defineProps<{
general: GeneralInfo | null;
loading: boolean;
}>();
</script>
<template>
<div class="general-card">
<div v-if="props.loading">
<SkeletonLines :lines="5" />
</div>
<div v-else-if="!props.general" class="empty">장수 정보를 불러오지 못했습니다.</div>
<div v-else class="general-body">
<div class="general-header">
<span class="name">{{ props.general.name }}</span>
<span class="meta">ID {{ props.general.id }} · 관직 {{ props.general.officerLevel }}</span>
</div>
<div class="stats">
<div>통솔 {{ props.general.stats.leadership }}</div>
<div>무력 {{ props.general.stats.strength }}</div>
<div>지력 {{ props.general.stats.intelligence }}</div>
</div>
<div class="resources">
<div> {{ props.general.gold }}</div>
<div> {{ props.general.rice }}</div>
<div> {{ props.general.crew }}</div>
</div>
<div class="status">
<div>훈련 {{ props.general.train }}</div>
<div>사기 {{ props.general.atmos }}</div>
<div>부상 {{ props.general.injury }}</div>
<div>경험 {{ props.general.experience }}</div>
<div>공헌 {{ props.general.dedication }}</div>
</div>
</div>
</div>
</template>
<style scoped>
.general-card {
display: flex;
flex-direction: column;
gap: 8px;
}
.general-header {
display: flex;
flex-direction: column;
gap: 4px;
}
.general-header .name {
font-size: 1.1rem;
font-weight: 600;
}
.general-header .meta {
font-size: 0.75rem;
color: rgba(232, 221, 196, 0.7);
}
.stats,
.resources,
.status {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
gap: 6px;
font-size: 0.85rem;
}
.empty {
color: rgba(232, 221, 196, 0.6);
}
</style>