Skip to content

Commit 754c8f0

Browse files
committed
chore: wip
1 parent c03a967 commit 754c8f0

File tree

1 file changed

+219
-10
lines changed
  • storage/framework/defaults/views/dashboard/commerce/gift-cards

1 file changed

+219
-10
lines changed

storage/framework/defaults/views/dashboard/commerce/gift-cards/index.vue

Lines changed: 219 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,114 @@
11
<script lang="ts" setup>
22
import { ref, computed } from 'vue'
33
import { useHead } from '@vueuse/head'
4+
import { Line, Bar } from 'vue-chartjs'
5+
import {
6+
Chart as ChartJS,
7+
CategoryScale,
8+
LinearScale,
9+
PointElement,
10+
LineElement,
11+
BarElement,
12+
Title,
13+
Tooltip,
14+
Legend,
15+
Filler,
16+
} from 'chart.js'
17+
18+
ChartJS.register(
19+
CategoryScale,
20+
LinearScale,
21+
PointElement,
22+
LineElement,
23+
BarElement,
24+
Title,
25+
Tooltip,
26+
Legend,
27+
Filler,
28+
)
429
530
useHead({
631
title: 'Dashboard - Commerce Gift Cards',
732
})
833
34+
// Chart options
35+
const chartOptions = {
36+
responsive: true,
37+
maintainAspectRatio: false,
38+
plugins: {
39+
legend: {
40+
display: false,
41+
},
42+
},
43+
scales: {
44+
y: {
45+
beginAtZero: true,
46+
grid: {
47+
display: true,
48+
color: 'rgba(0, 0, 0, 0.05)',
49+
},
50+
},
51+
x: {
52+
grid: {
53+
display: false,
54+
},
55+
},
56+
},
57+
}
58+
59+
// Generate monthly data for charts
60+
const monthlyChartData = computed(() => {
61+
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
62+
63+
// Sample data - in a real app, this would be calculated from actual usage data
64+
const salesData = [2, 3, 5, 4, 6, 8, 7, 10, 12, 15, 18, 20]
65+
const revenueData = [100, 150, 250, 200, 300, 400, 350, 500, 600, 750, 900, 1000]
66+
67+
// Gift card sales chart data
68+
const giftCardSalesData = {
69+
labels: months,
70+
datasets: [
71+
{
72+
label: 'Gift Card Sales',
73+
backgroundColor: 'rgba(59, 130, 246, 0.2)',
74+
borderColor: 'rgba(59, 130, 246, 1)',
75+
borderWidth: 2,
76+
pointBackgroundColor: 'rgba(59, 130, 246, 1)',
77+
pointBorderColor: '#fff',
78+
pointHoverBackgroundColor: '#fff',
79+
pointHoverBorderColor: 'rgba(59, 130, 246, 1)',
80+
fill: true,
81+
tension: 0.4,
82+
data: salesData,
83+
},
84+
],
85+
}
86+
87+
// Gift card revenue chart data
88+
const giftCardRevenueData = {
89+
labels: months,
90+
datasets: [
91+
{
92+
label: 'Gift Card Revenue',
93+
backgroundColor: 'rgba(16, 185, 129, 0.8)',
94+
borderColor: 'rgba(16, 185, 129, 1)',
95+
borderWidth: 1,
96+
borderRadius: 4,
97+
data: revenueData,
98+
},
99+
],
100+
}
101+
102+
return {
103+
giftCardSalesData,
104+
giftCardRevenueData
105+
}
106+
})
107+
108+
// Time range selector
109+
const timeRange = ref('Last 30 days')
110+
const timeRanges = ['Today', 'Last 7 days', 'Last 30 days', 'Last 90 days', 'Last year', 'All time']
111+
9112
// Define gift card type
10113
interface GiftCard {
11114
id: number
@@ -102,6 +205,33 @@ const statusFilter = ref('all')
102205
// Available statuses
103206
const statuses = ['all', 'Active', 'Used', 'Expired']
104207
208+
// Computed gift card statistics
209+
const giftCardStats = computed(() => {
210+
const activeGiftCards = giftCards.value.filter(c => c.status === 'Active').length
211+
const totalGiftCards = giftCards.value.length
212+
213+
// Calculate total initial value and current balance
214+
const totalInitialValue = giftCards.value.reduce((sum, card) => sum + card.initialValue, 0)
215+
const totalCurrentBalance = giftCards.value.reduce((sum, card) => sum + card.currentBalance, 0)
216+
217+
// Calculate amount redeemed
218+
const totalRedeemed = totalInitialValue - totalCurrentBalance
219+
220+
// Calculate redemption rate
221+
const redemptionRate = totalInitialValue > 0
222+
? ((totalRedeemed / totalInitialValue) * 100).toFixed(1)
223+
: '0.0'
224+
225+
return {
226+
activeGiftCards,
227+
totalGiftCards,
228+
totalInitialValue: totalInitialValue.toFixed(2),
229+
totalCurrentBalance: totalCurrentBalance.toFixed(2),
230+
totalRedeemed: totalRedeemed.toFixed(2),
231+
redemptionRate
232+
}
233+
})
234+
105235
// Computed filtered and sorted gift cards
106236
const filteredGiftCards = computed(() => {
107237
return giftCards.value
@@ -158,27 +288,29 @@ function getStatusClass(status: string): string {
158288
}
159289
}
160290
291+
// Define global date variables
292+
const currentDate = new Date().toISOString().split('T')[0] as string
293+
const oneYearFromNow = new Date()
294+
oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1)
295+
const futureDate = oneYearFromNow.toISOString().split('T')[0] as string
296+
161297
// Modal state
162298
const showAddModal = ref(false)
163299
const newGiftCard = ref<NewGiftCard>({
164300
code: '',
165301
initialValue: 50,
166302
recipient: '',
167303
email: '',
168-
expiryDate: ''
304+
expiryDate: futureDate
169305
})
170306
171307
function openAddModal(): void {
172-
// Set expiry date to one year from now
173-
const oneYearFromNow = new Date()
174-
oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1)
175-
176308
newGiftCard.value = {
177309
code: generateGiftCardCode(),
178310
initialValue: 50,
179311
recipient: '',
180312
email: '',
181-
expiryDate: oneYearFromNow.toISOString().split('T')[0]
313+
expiryDate: futureDate
182314
}
183315
showAddModal.value = true
184316
}
@@ -216,13 +348,12 @@ function generateGiftCardCode(): string {
216348
function addGiftCard(): void {
217349
// In a real app, this would send data to the server
218350
const id = Math.max(...giftCards.value.map(c => c.id)) + 1
219-
const today = new Date().toISOString().split('T')[0]
220351
221352
// Ensure we have non-null values with default values
222353
const code = newGiftCard.value.code || generateGiftCardCode()
223354
const recipient = newGiftCard.value.recipient || 'Anonymous'
224355
const email = newGiftCard.value.email || ''
225-
const expiryDate = newGiftCard.value.expiryDate || today
356+
const expiryDate = newGiftCard.value.expiryDate || futureDate
226357
227358
giftCards.value.push({
228359
id,
@@ -232,7 +363,7 @@ function addGiftCard(): void {
232363
recipient,
233364
email,
234365
purchasedBy: 'Current User', // In a real app, this would be the logged-in user
235-
purchaseDate: today,
366+
purchaseDate: currentDate,
236367
expiryDate,
237368
status: 'Active'
238369
})
@@ -263,8 +394,80 @@ function addGiftCard(): void {
263394
</div>
264395
</div>
265396

397+
<!-- Time range selector -->
398+
<div class="mt-4 flex items-center justify-between">
399+
<p class="text-sm text-gray-500 dark:text-gray-400">
400+
Overview of your gift card performance
401+
</p>
402+
<div class="relative">
403+
<select v-model="timeRange" class="block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-blue-600 sm:text-sm sm:leading-6 dark:bg-blue-gray-800 dark:text-white dark:ring-gray-700">
404+
<option v-for="range in timeRanges" :key="range" :value="range">{{ range }}</option>
405+
</select>
406+
</div>
407+
</div>
408+
409+
<!-- Stats -->
410+
<dl class="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4">
411+
<div class="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6 dark:bg-blue-gray-800">
412+
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-300">Active Gift Cards</dt>
413+
<dd class="mt-1 text-3xl font-semibold tracking-tight text-gray-900 dark:text-white">{{ giftCardStats.activeGiftCards }}</dd>
414+
<dd class="mt-2 flex items-center text-sm text-green-600 dark:text-green-400">
415+
<div class="i-hugeicons-analytics-up h-4 w-4 mr-1"></div>
416+
<span>{{ Math.round(giftCardStats.activeGiftCards / giftCardStats.totalGiftCards * 100) }}% of total</span>
417+
</dd>
418+
</div>
419+
420+
<div class="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6 dark:bg-blue-gray-800">
421+
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-300">Total Value</dt>
422+
<dd class="mt-1 text-3xl font-semibold tracking-tight text-gray-900 dark:text-white">${{ parseFloat(giftCardStats.totalInitialValue).toLocaleString() }}</dd>
423+
<dd class="mt-2 flex items-center text-sm text-green-600 dark:text-green-400">
424+
<div class="i-hugeicons-analytics-up h-4 w-4 mr-1"></div>
425+
<span>10.5% increase</span>
426+
</dd>
427+
</div>
428+
429+
<div class="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6 dark:bg-blue-gray-800">
430+
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-300">Current Balance</dt>
431+
<dd class="mt-1 text-3xl font-semibold tracking-tight text-gray-900 dark:text-white">${{ parseFloat(giftCardStats.totalCurrentBalance).toLocaleString() }}</dd>
432+
<dd class="mt-2 flex items-center text-sm text-blue-600 dark:text-blue-400">
433+
<div class="i-hugeicons-analytics-up h-4 w-4 mr-1"></div>
434+
<span>${{ parseFloat(giftCardStats.totalRedeemed).toLocaleString() }} redeemed</span>
435+
</dd>
436+
</div>
437+
438+
<div class="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6 dark:bg-blue-gray-800">
439+
<dt class="truncate text-sm font-medium text-gray-500 dark:text-gray-300">Redemption Rate</dt>
440+
<dd class="mt-1 text-3xl font-semibold tracking-tight text-gray-900 dark:text-white">{{ giftCardStats.redemptionRate }}%</dd>
441+
<dd class="mt-2 flex items-center text-sm text-green-600 dark:text-green-400">
442+
<div class="i-hugeicons-analytics-up h-4 w-4 mr-1"></div>
443+
<span>5.2% increase</span>
444+
</dd>
445+
</div>
446+
</dl>
447+
448+
<!-- Charts -->
449+
<div class="mt-8 grid grid-cols-1 gap-5 lg:grid-cols-2">
450+
<div class="overflow-hidden rounded-lg bg-white shadow dark:bg-blue-gray-800">
451+
<div class="p-6">
452+
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">Gift Card Sales</h3>
453+
<div class="mt-2 h-80">
454+
<Line :data="monthlyChartData.giftCardSalesData" :options="chartOptions" />
455+
</div>
456+
</div>
457+
</div>
458+
459+
<div class="overflow-hidden rounded-lg bg-white shadow dark:bg-blue-gray-800">
460+
<div class="p-6">
461+
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">Gift Card Revenue</h3>
462+
<div class="mt-2 h-80">
463+
<Bar :data="monthlyChartData.giftCardRevenueData" :options="chartOptions" />
464+
</div>
465+
</div>
466+
</div>
467+
</div>
468+
266469
<!-- Filters -->
267-
<div class="mt-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
470+
<div class="mt-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
268471
<div class="relative max-w-sm">
269472
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
270473
<div class="i-hugeicons-search-01 h-5 w-5 text-gray-400"></div>
@@ -292,6 +495,12 @@ function addGiftCard(): void {
292495

293496
<!-- Gift Cards table -->
294497
<div class="mt-6 flow-root">
498+
<div class="sm:flex sm:items-center sm:justify-between mb-4">
499+
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">All Gift Cards</h3>
500+
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
501+
A list of all the gift cards in your store including their value, balance, and status.
502+
</p>
503+
</div>
295504
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
296505
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
297506
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg">

0 commit comments

Comments
 (0)