Skip to content

Commit 75e1173

Browse files
committed
fix: improve offline mode, UI responsiveness, and list view functionality
- Add offline mode fixes to prevent network errors when offline - Fix InvoiceCart to check offline status before loading customers/offers - Fix useInvoice to skip draft cleanup when offline - Add proper offline checks in giftCards watcher - Fix offline invoice delete to work on first attempt - Add watcher on pendingInvoices prop in OfflineInvoicesDialog - Prevent race condition where UI showed stale data after delete - Make Offline Invoices Dialog mobile responsive - Add responsive layouts for header, invoice list, and dialogs - Reduce font sizes and padding on mobile screens - Make buttons full-width on mobile for better touch targets - Add proper text truncation to prevent overflow - Fix list view table header to stay fixed when scrolling - Increase z-index from z-0 to z-10 on thead and th elements - Header now properly stays on top of scrolling content - Add Clear Cache overlay with smooth animations - Create new ClearCacheOverlay component - Replace dialog with overlay for better UX - Improve cache status tooltip interaction - Make tooltip click-to-toggle instead of hover - Center tooltip under icon and make responsive - Clean up code to be more minimal and efficient
1 parent 9c2e5f4 commit 75e1173

16 files changed

Lines changed: 772 additions & 208 deletions

POS/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ declare module 'vue' {
1111
ActionButton: typeof import('./src/components/common/ActionButton.vue')['default']
1212
BatchSerialDialog: typeof import('./src/components/sale/BatchSerialDialog.vue')['default']
1313
CheckboxField: typeof import('./src/components/settings/CheckboxField.vue')['default']
14+
ClearCacheOverlay: typeof import('./src/components/common/ClearCacheOverlay.vue')['default']
1415
CouponDialog: typeof import('./src/components/sale/CouponDialog.vue')['default']
1516
CreateCustomerDialog: typeof import('./src/components/sale/CreateCustomerDialog.vue')['default']
1617
CustomerDialog: typeof import('./src/components/sale/CustomerDialog.vue')['default']
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<template>
2+
<Teleport to="body">
3+
<Transition name="overlay">
4+
<div
5+
v-if="show"
6+
class="fixed inset-0 z-[9999] flex items-center justify-center"
7+
>
8+
<!-- Backdrop -->
9+
<div class="absolute inset-0 bg-black/60 backdrop-blur-sm"></div>
10+
11+
<!-- Content Card -->
12+
<div class="relative z-10">
13+
<Transition name="card" mode="out-in">
14+
<div
15+
v-if="!isClearing"
16+
key="confirm"
17+
class="bg-white rounded-2xl shadow-2xl p-8 max-w-md mx-4 transform"
18+
>
19+
<!-- Icon -->
20+
<div class="flex justify-center mb-6">
21+
<div class="w-20 h-20 bg-red-100 rounded-full flex items-center justify-center">
22+
<svg
23+
class="w-10 h-10 text-red-600"
24+
fill="none"
25+
stroke="currentColor"
26+
viewBox="0 0 24 24"
27+
>
28+
<path
29+
stroke-linecap="round"
30+
stroke-linejoin="round"
31+
stroke-width="2"
32+
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
33+
/>
34+
</svg>
35+
</div>
36+
</div>
37+
38+
<!-- Title & Message -->
39+
<h3 class="text-2xl font-bold text-gray-900 text-center mb-3">
40+
Clear Cache?
41+
</h3>
42+
<p class="text-gray-600 text-center mb-8 leading-relaxed">
43+
This will clear all cached items, customers, and stock data. Invoices and drafts will be preserved.
44+
</p>
45+
46+
<!-- Buttons -->
47+
<div class="flex gap-3">
48+
<button
49+
@click="$emit('cancel')"
50+
class="flex-1 px-6 py-3 bg-gray-100 hover:bg-gray-200 text-gray-700 font-semibold rounded-xl transition-all active:scale-95"
51+
>
52+
Cancel
53+
</button>
54+
<button
55+
@click="handleConfirm"
56+
class="flex-1 px-6 py-3 bg-red-600 hover:bg-red-700 text-white font-semibold rounded-xl transition-all active:scale-95 shadow-lg shadow-red-500/30"
57+
>
58+
Clear Cache
59+
</button>
60+
</div>
61+
</div>
62+
63+
<!-- Clearing Animation -->
64+
<div
65+
v-else
66+
key="clearing"
67+
class="bg-white rounded-2xl shadow-2xl p-12 max-w-md mx-4 transform"
68+
>
69+
<div class="flex flex-col items-center">
70+
<!-- Animated Icon Container -->
71+
<div class="relative mb-6">
72+
<!-- Outer spinning ring -->
73+
<div class="w-24 h-24 rounded-full border-4 border-blue-200 border-t-blue-600 animate-spin"></div>
74+
75+
<!-- Inner icon -->
76+
<div class="absolute inset-0 flex items-center justify-center">
77+
<svg
78+
class="w-10 h-10 text-blue-600 animate-pulse"
79+
fill="currentColor"
80+
viewBox="0 0 24 24"
81+
>
82+
<path d="M12 2C8.13 2 5 3.12 5 4.5V7c0 1.38 3.13 2.5 7 2.5S19 8.38 19 7V4.5C19 3.12 15.87 2 12 2zM5 9v3c0 1.38 3.13 2.5 7 2.5s7-1.12 7-2.5V9c0 1.38-3.13 2.5-7 2.5S5 10.38 5 9zm0 5v3c0 1.38 3.13 2.5 7 2.5s7-1.12 7-2.5v-3c0 1.38-3.13 2.5-7 2.5S5 15.38 5 14z"/>
83+
</svg>
84+
</div>
85+
</div>
86+
87+
<!-- Text -->
88+
<h3 class="text-xl font-bold text-gray-900 mb-2">
89+
Clearing Cache...
90+
</h3>
91+
<p class="text-gray-500 text-center">
92+
Please wait while we clear your cached data
93+
</p>
94+
95+
<!-- Progress dots animation -->
96+
<div class="flex gap-2 mt-6">
97+
<div class="w-2 h-2 bg-blue-600 rounded-full animate-bounce" style="animation-delay: 0ms"></div>
98+
<div class="w-2 h-2 bg-blue-600 rounded-full animate-bounce" style="animation-delay: 150ms"></div>
99+
<div class="w-2 h-2 bg-blue-600 rounded-full animate-bounce" style="animation-delay: 300ms"></div>
100+
</div>
101+
</div>
102+
</div>
103+
</Transition>
104+
</div>
105+
</div>
106+
</Transition>
107+
</Teleport>
108+
</template>
109+
110+
<script setup>
111+
import { ref } from 'vue'
112+
113+
defineProps({
114+
show: {
115+
type: Boolean,
116+
default: false
117+
}
118+
})
119+
120+
const emit = defineEmits(['cancel', 'confirm'])
121+
122+
const isClearing = ref(false)
123+
124+
function handleConfirm() {
125+
isClearing.value = true
126+
emit('confirm')
127+
}
128+
129+
// Reset state when overlay is closed
130+
function reset() {
131+
isClearing.value = false
132+
}
133+
134+
// Expose reset method to parent
135+
defineExpose({ reset })
136+
</script>
137+
138+
<style scoped>
139+
/* Overlay transitions */
140+
.overlay-enter-active,
141+
.overlay-leave-active {
142+
transition: opacity 0.3s ease;
143+
}
144+
145+
.overlay-enter-from,
146+
.overlay-leave-to {
147+
opacity: 0;
148+
}
149+
150+
.overlay-enter-active .absolute:first-child {
151+
transition: backdrop-filter 0.3s ease;
152+
}
153+
154+
/* Card transitions */
155+
.card-enter-active,
156+
.card-leave-active {
157+
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
158+
}
159+
160+
.card-enter-from {
161+
opacity: 0;
162+
transform: scale(0.9) translateY(-20px);
163+
}
164+
165+
.card-leave-to {
166+
opacity: 0;
167+
transform: scale(0.9) translateY(20px);
168+
}
169+
170+
/* Bounce animation for dots */
171+
@keyframes bounce {
172+
0%, 100% {
173+
transform: translateY(0);
174+
}
175+
50% {
176+
transform: translateY(-10px);
177+
}
178+
}
179+
180+
.animate-bounce {
181+
animation: bounce 0.6s ease-in-out infinite;
182+
}
183+
</style>

0 commit comments

Comments
 (0)