ui polish

This commit is contained in:
2026-03-08 02:29:39 +01:00
parent 8b1a96f133
commit 3eccedfad4
18 changed files with 217 additions and 35 deletions

View File

@@ -1,8 +1,10 @@
<script setup lang="ts">
import { ref } from 'vue'
import { RouterLink } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
const auth = useAuthStore()
const showLogoutConfirm = ref(false)
</script>
<template>
@@ -27,9 +29,6 @@ const auth = useAuthStore()
<li class="nav-item">
<RouterLink class="nav-link" active-class="active" to="/test">Test</RouterLink>
</li>
<li class="nav-item">
<RouterLink class="nav-link" active-class="active" to="/about">About</RouterLink>
</li>
</ul>
<ul class="navbar-nav">
@@ -38,7 +37,7 @@ const auth = useAuthStore()
<span class="nav-link text-light">{{ auth.user?.username }}</span>
</li>
<li class="nav-item">
<button class="btn btn-outline-light btn-sm my-1" @click="auth.logout()">
<button class="btn btn-outline-light btn-sm my-1" @click="showLogoutConfirm = true">
Logout
</button>
</li>
@@ -55,4 +54,46 @@ const auth = useAuthStore()
</div>
</div>
</nav>
<Teleport to="body">
<div
v-if="showLogoutConfirm"
class="modal d-block"
tabindex="-1"
style="background: rgba(0,0,0,0.5)"
@click.self="showLogoutConfirm = false"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header border-0 pb-0">
<h5 class="modal-title">Logout</h5>
<button
type="button"
class="btn-close"
@click="showLogoutConfirm = false"
></button>
</div>
<div class="modal-body">
Are you sure you want to logout?
</div>
<div class="modal-footer border-0 pt-0">
<button
type="button"
class="btn btn-outline-secondary"
@click="showLogoutConfirm = false"
>
Cancel
</button>
<button
type="button"
class="btn btn-danger"
@click="showLogoutConfirm = false; auth.logout()"
>
Yes, logout
</button>
</div>
</div>
</div>
</div>
</Teleport>
</template>

View File

@@ -19,7 +19,7 @@ const handleClick = () => emit('click', props.whiteboard)
@click="handleClick"
>
<div class="d-flex justify-content-between align-items-start mb-2">
<h5 class="mb-0 text-dark">{{ whiteboard.title }}</h5>
<h5 class="mb-0">{{ whiteboard.title }}</h5>
<small class="text-muted">{{ formatDate(whiteboard.createdAt) }}</small>
</div>
</div>

View File

@@ -18,7 +18,7 @@ import RecentWhiteboardsList from './RecentWhiteboardsList.vue'
</h5>
<button
type="button"
class="btn-close btn-close-white"
class="btn-close"
data-bs-dismiss="offcanvas"
aria-label="Close"
/>

View File

@@ -44,7 +44,7 @@ const handleConfirmDelete = (e: MouseEvent) => {
@click="handleClick"
>
<div class="d-flex justify-content-between align-items-start mb-2">
<h5 class="mb-0 text-dark">{{ whiteboard.title }}</h5>
<h5 class="mb-0">{{ whiteboard.title }}</h5>
<div class="d-flex align-items-center gap-2">
<small class="text-muted">{{ formatDate(whiteboard.createdAt) }}</small>
<button

View File

@@ -18,7 +18,7 @@ import WhiteboardHistoryList from './WhiteboardHistoryList.vue'
</h5>
<button
type="button"
class="btn-close btn-close-white"
class="btn-close"
data-bs-dismiss="offcanvas"
aria-label="Close"
/>

View File

@@ -2,18 +2,21 @@
import {computed, ref} from 'vue'
import { useWhiteboardStore } from '@/stores/whiteboard.ts'
import { useWhiteboardsStore } from "@/stores/whiteboards.ts";
import { useAuthStore } from '@/stores/auth'
import { avatarColorFromString } from '@/composables/useShapeOwner'
import type { ShapeTool, Arrow, Line, Rectangle, TextShape } from '@/types/whiteboard.ts'
const sessionStore = useWhiteboardStore()
const infoStore = useWhiteboardsStore()
const auth = useAuthStore()
const emit = defineEmits<{ leave: [] }>()
const tools: { name: ShapeTool; label: string; icon: string; enabled: boolean }[] = [
{ name: 'hand', label: 'Select', icon: '\u270B', enabled: true },
{ name: 'rectangle', label: 'Rectangle', icon: '\u25AD', enabled: true },
{ name: 'arrow', label: 'Arrow', icon: '\u2192', enabled: true },
{ name: 'line', label: 'Line', icon: '\u2571', enabled: true },
{ name: 'text', label: 'Text', icon: 'T', enabled: true },
{ name: 'hand', label: 'Select', icon: 'bi-cursor', enabled: true },
{ name: 'rectangle', label: 'Rectangle', icon: 'bi-square', enabled: true },
{ name: 'arrow', label: 'Arrow', icon: 'bi-arrow-up-right', enabled: true },
{ name: 'line', label: 'Line', icon: 'bi-slash-lg', enabled: true },
{ name: 'text', label: 'Text', icon: 'bi-fonts', enabled: true },
]
const colors = ['#4f9dff', '#ff4f4f', '#4fff4f', '#ffff4f', '#ff4fff', '#ffffff', '#ff9f4f', '#4fffff']
@@ -86,7 +89,7 @@ const copyCodeToClipboard = async () => {
:title="tool.enabled ? tool.label : `${tool.label} (coming soon)`"
@click="tool.enabled && sessionStore.selectTool(tool.name)"
>
{{ tool.icon }}
<i :class="['bi', tool.icon]"></i>
</button>
</div>
@@ -140,6 +143,28 @@ const copyCodeToClipboard = async () => {
</div>
</div>
<div v-if="sessionStore.connectedUsers.length" class="participants-panel">
<div class="property-label">Participants ({{ sessionStore.connectedUsers.length }})</div>
<div class="participants-list">
<div
v-for="user in sessionStore.connectedUsers"
:key="user.userId"
class="participant"
>
<span
class="participant-avatar"
:style="{ backgroundColor: avatarColorFromString(user.username || user.userId) }"
>
{{ (user.username || '?').charAt(0).toUpperCase() }}
</span>
<span class="participant-name">
{{ user.username || 'Unknown' }}
<span v-if="user.userId === auth.user?.userId" class="you-label">(You)</span>
</span>
</div>
</div>
</div>
<div class="toolbar-footer">
<div class="position-relative mb-2">
<button
@@ -253,6 +278,52 @@ const copyCodeToClipboard = async () => {
accent-color: #4f9dff;
}
.participants-panel {
margin-top: 12px;
border-top: 1px solid #2a2a3e;
padding-top: 10px;
}
.participants-list {
display: flex;
flex-direction: column;
gap: 6px;
max-height: 160px;
overflow-y: auto;
}
.participant {
display: flex;
align-items: center;
gap: 8px;
}
.participant-avatar {
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 700;
color: #fff;
flex-shrink: 0;
}
.participant-name {
font-size: 13px;
color: rgba(255, 255, 255, 0.85);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.you-label {
color: #8a8a9e;
font-size: 11px;
}
.toolbar-footer {
margin-top: auto;
padding-top: 8px;