@meeovi/layer-commerce 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/catalog/product/ProductAccordion/types.ts +3 -3
- package/app/components/catalog/product/ProductProperties/types.ts +3 -3
- package/app/components/catalog/product/ProductSlider/types.ts +5 -5
- package/app/components/catalog/product/RecommendedProducts/types.ts +3 -3
- package/app/components/catalog/product/bestsellers.vue +8 -20
- package/app/components/catalog/product/deals.vue +7 -22
- package/app/components/catalog/product/exclusives.vue +8 -10
- package/app/components/catalog/product/featuredproducts.vue +8 -20
- package/app/components/catalog/product/latestproducts.vue +8 -20
- package/app/components/catalog/product/productCard.vue +55 -21
- package/app/components/catalog/product/productDetails.vue +20 -14
- package/app/components/catalog/product/relatedproducts.vue +5 -20
- package/app/components/catalog/product/sizeOptions.vue +3 -8
- package/app/components/catalog/shops/relatedstores.vue +6 -21
- package/app/components/categories/chart/[id].vue +200 -0
- package/app/components/categories/chart/add-chart.vue +142 -0
- package/app/components/categories/chart/chart.vue +82 -0
- package/app/components/categories/chart/monthlyChart.vue +46 -0
- package/app/components/categories/chart/weeklyChart.vue +46 -0
- package/app/components/categories/chart/yearlyChart.vue +46 -0
- package/app/components/categories/charts.vue +118 -0
- package/app/components/categories/deals.vue +101 -0
- package/app/components/categories/eats.vue +49 -0
- package/app/components/categories/restaurants.vue +26 -0
- package/app/components/categories/station/[id].vue +72 -0
- package/app/components/categories/stations.vue +124 -0
- package/app/components/categories/time/time.vue +63 -0
- package/app/components/categories/travel.vue +75 -0
- package/app/components/categories/weather/weather.vue +44 -0
- package/app/components/content/pages/showcases.vue +1 -1
- package/app/components/marketing/promotions/giftcards.vue +20 -45
- package/app/components/marketing/promotions/subscriptions.vue +8 -21
- package/app/components/placeholders/Comments.vue +15 -0
- package/app/components/placeholders/CreateListBtn.vue +7 -0
- package/app/components/placeholders/Event.vue +9 -0
- package/app/components/placeholders/ListShowcases.vue +9 -0
- package/app/components/placeholders/Short.vue +9 -0
- package/app/components/placeholders/Space.vue +9 -0
- package/app/components/placeholders/Tag.vue +7 -0
- package/app/components/sales/CheckoutAddress/types.ts +12 -11
- package/app/components/sales/OrderSummary/types.ts +3 -3
- package/app/components/sales/incentives.vue +13 -37
- package/app/composables/cart/registry.ts +7 -0
- package/app/composables/index.ts +1 -0
- package/app/composables/products/registry.ts +7 -0
- package/app/composables/registry.ts +21 -0
- package/app/composables/useCatalog.ts +64 -0
- package/app/composables/useContent.ts +57 -0
- package/app/composables/useProducts/types.ts +15 -10
- package/app/pages/brand/[...slug].vue +1 -1
- package/app/pages/departments/[...slug].vue +385 -0
- package/app/pages/departments/category/[...slug].vue +135 -0
- package/app/pages/product/[...id].vue +3 -3
- package/app/pages/shop/[...slug].vue +12 -18
- package/app/pages/shops.vue +18 -25
- package/global.d.ts +14 -0
- package/package.json +2 -1
- package/tsconfig.json +10 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="contentPage">
|
|
3
|
+
<v-row>
|
|
4
|
+
<v-col cols="12">
|
|
5
|
+
<v-card :color="chartbar?.color">
|
|
6
|
+
<div class="d-flex flex-no-wrap justify-space-between">
|
|
7
|
+
<div>
|
|
8
|
+
<v-card-title class="text-h5">
|
|
9
|
+
{{ chart?.name }}
|
|
10
|
+
</v-card-title>
|
|
11
|
+
|
|
12
|
+
<v-card-subtitle>{{ chart?.description }}</v-card-subtitle>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<v-avatar class="ma-3" rounded="0" size="125">
|
|
16
|
+
<NuxtImg :src="`${$directus.url}/assets/${chart?.image?.filename_disk}`" />
|
|
17
|
+
</v-avatar>
|
|
18
|
+
</div>
|
|
19
|
+
</v-card>
|
|
20
|
+
</v-col>
|
|
21
|
+
|
|
22
|
+
<v-col cols="12">
|
|
23
|
+
<v-card elevation="0">
|
|
24
|
+
<v-tabs v-model="tab" :bg-color="chartbar?.color">
|
|
25
|
+
<div v-for="(menu, index) in spacebar?.menus" :key="index">
|
|
26
|
+
<v-tab :value="menu?.value">{{ menu?.name }}</v-tab>
|
|
27
|
+
</div>
|
|
28
|
+
</v-tabs>
|
|
29
|
+
|
|
30
|
+
<v-card-text>
|
|
31
|
+
<v-tabs-window v-model="tab">
|
|
32
|
+
<v-tabs-window-item :value="chartbar?.menus[0]?.value">
|
|
33
|
+
<!-- Weekly Chart Table -->
|
|
34
|
+
<WeeklyChart :data="topProducts" />
|
|
35
|
+
</v-tabs-window-item>
|
|
36
|
+
<v-tabs-window-item :value="chartbar?.menus[1]?.value">
|
|
37
|
+
<!-- Monthly Chart Table -->
|
|
38
|
+
<MonthlyChart :data="topProducts" />
|
|
39
|
+
</v-tabs-window-item>
|
|
40
|
+
<v-tabs-window-item :value="chartbar?.menus[2]?.value">
|
|
41
|
+
<!-- Yearly Chart Table -->
|
|
42
|
+
<YearlyChart :data="topProducts" />
|
|
43
|
+
</v-tabs-window-item>
|
|
44
|
+
|
|
45
|
+
<v-tabs-window-item :value="chartbar?.menus[3]?.value">
|
|
46
|
+
<v-row>
|
|
47
|
+
<v-col v-for="charts in charts" :key="charts">
|
|
48
|
+
<charts :chart="charts" />
|
|
49
|
+
</v-col>
|
|
50
|
+
</v-row>
|
|
51
|
+
</v-tabs-window-item>
|
|
52
|
+
</v-tabs-window>
|
|
53
|
+
</v-card-text>
|
|
54
|
+
</v-card>
|
|
55
|
+
</v-col>
|
|
56
|
+
</v-row>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<script setup>
|
|
61
|
+
import {
|
|
62
|
+
ref,
|
|
63
|
+
computed
|
|
64
|
+
} from 'vue'
|
|
65
|
+
import WeeklyChart from '@/components/charts/weeklyChart.vue'
|
|
66
|
+
import MonthlyChart from '@/components/charts/monthlyChart.vue'
|
|
67
|
+
import YearlyChart from '@/components/charts/yearlyChart.vue'
|
|
68
|
+
|
|
69
|
+
const tab = ref('weekly')
|
|
70
|
+
const route = useRoute()
|
|
71
|
+
const topProducts = ref([]);
|
|
72
|
+
|
|
73
|
+
// Add new reactive references
|
|
74
|
+
const filterOptions = ref({
|
|
75
|
+
category: null,
|
|
76
|
+
timeRange: 'weekly'
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const sortOptions = ref({
|
|
80
|
+
field: 'sales',
|
|
81
|
+
order: 'desc'
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
const {
|
|
85
|
+
$directus,
|
|
86
|
+
$readItem,
|
|
87
|
+
$readItems
|
|
88
|
+
} = useNuxtApp()
|
|
89
|
+
|
|
90
|
+
const {
|
|
91
|
+
data: chart
|
|
92
|
+
} = await useAsyncData('chart', () => {
|
|
93
|
+
return $directus.request($readItem('musicchart', route.params.id, {
|
|
94
|
+
fields: ['*', {
|
|
95
|
+
'*': ['*']
|
|
96
|
+
}]
|
|
97
|
+
}))
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const {
|
|
101
|
+
data: charts
|
|
102
|
+
} = await useAsyncData('charts', () => {
|
|
103
|
+
return $directus.request($readItems('musicchart', {
|
|
104
|
+
fields: ['*', {
|
|
105
|
+
'*': ['*']
|
|
106
|
+
}]
|
|
107
|
+
}))
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const {
|
|
111
|
+
data: chartbar
|
|
112
|
+
} = await useAsyncData('chartbar', () => {
|
|
113
|
+
return $directus.request($readItem('navigation', '53'))
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const categories = ref([]) // Will be populated from your products data
|
|
117
|
+
|
|
118
|
+
// Calculate helper functions
|
|
119
|
+
const calculateTrend = (current, previous) => {
|
|
120
|
+
if (current > previous) return 'up';
|
|
121
|
+
if (current < previous) return 'down';
|
|
122
|
+
return 'stable';
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const calculateWeeksOnChart = (firstAppearance) => {
|
|
126
|
+
const now = new Date();
|
|
127
|
+
const start = new Date(firstAppearance);
|
|
128
|
+
return Math.floor((now - start) / (7 * 24 * 60 * 60 * 1000));
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// Modify your existing fetchChartData function
|
|
132
|
+
const fetchChartData = async (timeframe) => {
|
|
133
|
+
try {
|
|
134
|
+
const now = new Date();
|
|
135
|
+
let startDate;
|
|
136
|
+
|
|
137
|
+
// Determine the start date based on the timeframe
|
|
138
|
+
if (timeframe === "weekly") {
|
|
139
|
+
startDate = new Date(now.setDate(now.getDate() - 7));
|
|
140
|
+
} else if (timeframe === "monthly") {
|
|
141
|
+
startDate = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
142
|
+
} else if (timeframe === "yearly") {
|
|
143
|
+
startDate = new Date(now.getFullYear(), 0, 1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const {
|
|
147
|
+
data
|
|
148
|
+
} = await useAsyncData("productChart", () => {
|
|
149
|
+
return $directus.request(
|
|
150
|
+
$readItems("products", {
|
|
151
|
+
sort: ["-sales"],
|
|
152
|
+
limit: 100,
|
|
153
|
+
filter: {
|
|
154
|
+
created_on: {
|
|
155
|
+
_gte: startDate.toISOString(),
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
})
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Process the data and calculate fields
|
|
163
|
+
const processedData = data.value.map((product) => ({
|
|
164
|
+
...product,
|
|
165
|
+
trend: calculateTrend(product.currentSales, product.previousSales),
|
|
166
|
+
weeksOnChart: calculateWeeksOnChart(product.firstAppearance),
|
|
167
|
+
}));
|
|
168
|
+
|
|
169
|
+
// Update top products and categories
|
|
170
|
+
topProducts.value = processedData;
|
|
171
|
+
categories.value = [...new Set(processedData.map((p) => p.category))];
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.error("Error fetching chart data:", error);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Watch for tab changes to update data
|
|
178
|
+
watch(tab, (newValue) => {
|
|
179
|
+
fetchChartData(newValue);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Filter and sort products
|
|
183
|
+
const sortedAndFilteredProducts = computed(() => {
|
|
184
|
+
let filtered = [...topProducts.value];
|
|
185
|
+
|
|
186
|
+
if (filterOptions.value.category) {
|
|
187
|
+
filtered = filtered.filter(
|
|
188
|
+
(product) => product.category === filterOptions.value.category
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return filtered.sort((a, b) => {
|
|
193
|
+
const aValue = a[sortOptions.value.field];
|
|
194
|
+
const bValue = b[sortOptions.value.field];
|
|
195
|
+
|
|
196
|
+
return sortOptions.value.order === 'asc' ?
|
|
197
|
+
aValue - bValue :
|
|
198
|
+
bValue - aValue;
|
|
199
|
+
});
|
|
200
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<form @submit.prevent="createActivityAndRefresh">
|
|
4
|
+
<v-card>
|
|
5
|
+
<v-card-text>
|
|
6
|
+
<v-text-field v-model="chartData.name" id="chartName" label="Chart Name*" required />
|
|
7
|
+
<v-textarea v-model="chartData.description" label="What's happening?*" variant="outlined"
|
|
8
|
+
required></v-textarea>
|
|
9
|
+
<v-row>
|
|
10
|
+
<v-col cols="6">
|
|
11
|
+
<v-select v-model="chartData.type" label="What type of chart is this?"
|
|
12
|
+
:items="['Notes', 'News']" />
|
|
13
|
+
</v-col>
|
|
14
|
+
<v-col cols="6">
|
|
15
|
+
<v-select v-model="chartData.status" label="Is this chart public or private?"
|
|
16
|
+
:items="['Public', 'Private']" />
|
|
17
|
+
</v-col>
|
|
18
|
+
<v-col cols="12">
|
|
19
|
+
<v-file-input @change="handleImageUpload" clearable density="compact"
|
|
20
|
+
prepend-icon="fas fa-image" accept="image/*" label="Image" variant="solo-inverted" />
|
|
21
|
+
</v-col>
|
|
22
|
+
</v-row>
|
|
23
|
+
</v-card-text>
|
|
24
|
+
<v-divider class="mt-12"></v-divider>
|
|
25
|
+
<v-card-actions>
|
|
26
|
+
<v-btn color="blue-darken-1" variant="text" @click="dialog = false">
|
|
27
|
+
Close
|
|
28
|
+
</v-btn>
|
|
29
|
+
<v-spacer></v-spacer>
|
|
30
|
+
<v-btn color="blue-darken-1" variant="text" type="submit" @click="reset = false">
|
|
31
|
+
Reset
|
|
32
|
+
</v-btn>
|
|
33
|
+
<v-btn color="blue-darken-1" variant="text" type="submit" @click="createNewChart">
|
|
34
|
+
Create
|
|
35
|
+
</v-btn>
|
|
36
|
+
</v-card-actions>
|
|
37
|
+
</v-card>
|
|
38
|
+
</form>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script>
|
|
43
|
+
export default {
|
|
44
|
+
methods: {
|
|
45
|
+
reset() {
|
|
46
|
+
this.$refs.form.reset()
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<script setup>
|
|
53
|
+
import {
|
|
54
|
+
ref
|
|
55
|
+
} from 'vue';
|
|
56
|
+
import {
|
|
57
|
+
useRoute } from 'vue-router';
|
|
58
|
+
import uploadFiles from '#shared/app/composables/globals/uploadFiles';
|
|
59
|
+
import createChart from '@/composables/charts/createChart';
|
|
60
|
+
|
|
61
|
+
// Make sure your props are properly defined
|
|
62
|
+
// Update props to include spaces_id
|
|
63
|
+
const props = defineProps({
|
|
64
|
+
spaces_id: {
|
|
65
|
+
type: String,
|
|
66
|
+
required: true
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const { user } = useSupabaseAuth()
|
|
71
|
+
|
|
72
|
+
const route = useRoute();
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
const chartData = ref({
|
|
76
|
+
name: '',
|
|
77
|
+
description: '',
|
|
78
|
+
type: '',
|
|
79
|
+
status: '',
|
|
80
|
+
image: '',
|
|
81
|
+
reactions: '',
|
|
82
|
+
color: '',
|
|
83
|
+
coverFile: null,
|
|
84
|
+
avatarFile: null,
|
|
85
|
+
creator: user?.email,
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const dialog = ref(false);
|
|
89
|
+
|
|
90
|
+
const imageFile = ref(null);
|
|
91
|
+
const documentFile = ref(null);
|
|
92
|
+
|
|
93
|
+
// Emit event for parent component updates
|
|
94
|
+
const emit = defineEmits(['chart-created']);
|
|
95
|
+
|
|
96
|
+
const handleImageUpload = (event) => {
|
|
97
|
+
imageFile.value = event.target.files[0];
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
const createNewChart = async () => {
|
|
102
|
+
try {
|
|
103
|
+
// Upload files if any
|
|
104
|
+
const uploadedFiles = await uploadFiles({
|
|
105
|
+
imageFile: imageFile.value,
|
|
106
|
+
documentFile: documentFile.value,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Update chart data with uploaded files
|
|
110
|
+
if (uploadedFiles) {
|
|
111
|
+
chartData.value.image = uploadedFiles.imageId;
|
|
112
|
+
chartData.value.media = uploadedFiles.documentId;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Set spaces_id in chartData to link chart to the space
|
|
116
|
+
chartData.value.spaces_id = props.spaces_id;
|
|
117
|
+
|
|
118
|
+
// Create the chart with space relationship
|
|
119
|
+
const chart = await createChart(chartData.value);
|
|
120
|
+
|
|
121
|
+
console.log('Created Chart:', chart);
|
|
122
|
+
|
|
123
|
+
// Emit event to refresh parent component
|
|
124
|
+
emit('chart-created', chart);
|
|
125
|
+
|
|
126
|
+
// Close dialog and reset form
|
|
127
|
+
dialog.value = false;
|
|
128
|
+
reset();
|
|
129
|
+
|
|
130
|
+
// Optional: Redirect to the space page
|
|
131
|
+
router.push(`/departments/categories/chart/${props.spaces_id}`);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('Error creating chart:', error);
|
|
134
|
+
// Add error handling here
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Add watch to update spaces_id if props change
|
|
139
|
+
watch(() => props.spaces_id, (newSpaceId) => {
|
|
140
|
+
chartData.value.spaces_id = newSpaceId;
|
|
141
|
+
});
|
|
142
|
+
</script>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="contentPage">
|
|
3
|
+
<v-toolbar :style="`background-color: ${chart?.color}`" :title="chart?.name"></v-toolbar>
|
|
4
|
+
<v-table class="charttable">
|
|
5
|
+
<thead>
|
|
6
|
+
<tr>
|
|
7
|
+
<th></th>
|
|
8
|
+
<th class="text-left">
|
|
9
|
+
This Week
|
|
10
|
+
</th>
|
|
11
|
+
<th class="text-left">Name</th>
|
|
12
|
+
<th class="text-left">
|
|
13
|
+
Award
|
|
14
|
+
</th>
|
|
15
|
+
<th class="text-left">
|
|
16
|
+
Last Week
|
|
17
|
+
</th>
|
|
18
|
+
<th class="text-left">
|
|
19
|
+
Peak Position
|
|
20
|
+
</th>
|
|
21
|
+
<th class="text-left">
|
|
22
|
+
Weeks on Chart
|
|
23
|
+
</th>
|
|
24
|
+
<th class="text-left">
|
|
25
|
+
Buy
|
|
26
|
+
</th>
|
|
27
|
+
<th class="text-left"><share /></th>
|
|
28
|
+
</tr>
|
|
29
|
+
</thead>
|
|
30
|
+
<tbody>
|
|
31
|
+
<tr v-for="(products, index) in chart?.products?.products_id" :key="index">
|
|
32
|
+
<td class="chartnumber">
|
|
33
|
+
<h1>{{ chart?.thisWeek }}</h1>
|
|
34
|
+
</td>
|
|
35
|
+
<td>
|
|
36
|
+
<v-avatar :image="products?.image?.filename_disk" rounded="0" size="130"></v-avatar>
|
|
37
|
+
</td>
|
|
38
|
+
<td>
|
|
39
|
+
<v-list>
|
|
40
|
+
<v-list-item>
|
|
41
|
+
<v-list-item-title>{{ products?.name }}</v-list-item-title>
|
|
42
|
+
<div v-for="product in products?.product_types?.product_types_id" :key="product">
|
|
43
|
+
<v-list-item-subtitle>{{ product?.name }}</v-list-item-subtitle>
|
|
44
|
+
</div>
|
|
45
|
+
</v-list-item>
|
|
46
|
+
</v-list>
|
|
47
|
+
</td>
|
|
48
|
+
<td>
|
|
49
|
+
<v-avatar icon="fas fa-star" :style="`color: ${chart?.award}`"></v-avatar>
|
|
50
|
+
</td>
|
|
51
|
+
<td>
|
|
52
|
+
<h5>{{ chart?.last_week }}</h5>
|
|
53
|
+
</td>
|
|
54
|
+
<td>
|
|
55
|
+
<h5>{{ chart?.peak_position }}</h5>
|
|
56
|
+
</td>
|
|
57
|
+
<td>
|
|
58
|
+
<h5>{{ chart?.weeks_on_chart }}</h5>
|
|
59
|
+
</td>
|
|
60
|
+
<td>
|
|
61
|
+
<v-btn href="" icon="fas fa-shopping-cart"></v-btn>
|
|
62
|
+
</td>
|
|
63
|
+
</tr>
|
|
64
|
+
</tbody>
|
|
65
|
+
</v-table>
|
|
66
|
+
<relatedchart />
|
|
67
|
+
<relatedproducts /><!---->
|
|
68
|
+
<recentlyviewed /><!---->
|
|
69
|
+
</div>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<script setup>
|
|
73
|
+
import share from '#social/app/components/blocks/share.vue'
|
|
74
|
+
import relatedchart from '../../related/relatedcharts.vue'
|
|
75
|
+
import relatedproducts from '#commerce/app/components/related/relatedproducts.vue'
|
|
76
|
+
import recentlyviewed from '#commerce/app/components/catalog/product/recentlyviewed.vue'
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
useHead({
|
|
80
|
+
title: computed(() => chart?.value?.name || 'Chart Page')
|
|
81
|
+
});
|
|
82
|
+
</script>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-table fixed-header>
|
|
3
|
+
<thead>
|
|
4
|
+
<tr>
|
|
5
|
+
<th class="text-left">Position</th>
|
|
6
|
+
<th class="text-left">Product</th>
|
|
7
|
+
<th class="text-left">Sales</th>
|
|
8
|
+
<th class="text-left">Last Week</th>
|
|
9
|
+
<th class="text-left">Peak Position</th>
|
|
10
|
+
<th class="text-left">Weeks on Chart</th>
|
|
11
|
+
<th class="text-left">Trend</th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
<tbody>
|
|
15
|
+
<tr v-for="(product, index) in data" :key="product.id">
|
|
16
|
+
<td>{{ index + 1 }}</td>
|
|
17
|
+
<td>
|
|
18
|
+
<div class="d-flex align-center">
|
|
19
|
+
<v-img :src="product.image" width="50" height="50" class="mr-3" />
|
|
20
|
+
<div>
|
|
21
|
+
<div class="font-weight-bold">{{ product.name }}</div>
|
|
22
|
+
<div class="text-caption">{{ product.category }}</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</td>
|
|
26
|
+
<td>{{ product.sales }}</td>
|
|
27
|
+
<td>
|
|
28
|
+
<v-chip :color="getPositionColor(product.lastWeek, index + 1)" size="small">
|
|
29
|
+
{{ product.lastWeek }}
|
|
30
|
+
</v-chip>
|
|
31
|
+
</td>
|
|
32
|
+
<td>{{ product.peakPosition }}</td>
|
|
33
|
+
<td>{{ product.weeksOnChart }}</td>
|
|
34
|
+
<td>
|
|
35
|
+
<v-icon :color="getTrendColor(product.trend)">{{ getTrendIcon(product.trend) }}</v-icon>
|
|
36
|
+
</td>
|
|
37
|
+
</tr>
|
|
38
|
+
</tbody>
|
|
39
|
+
</v-table>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup>
|
|
43
|
+
defineProps({
|
|
44
|
+
data: Array, // Accepts the chart data
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-table fixed-header>
|
|
3
|
+
<thead>
|
|
4
|
+
<tr>
|
|
5
|
+
<th class="text-left">Position</th>
|
|
6
|
+
<th class="text-left">Product</th>
|
|
7
|
+
<th class="text-left">Sales</th>
|
|
8
|
+
<th class="text-left">Last Week</th>
|
|
9
|
+
<th class="text-left">Peak Position</th>
|
|
10
|
+
<th class="text-left">Weeks on Chart</th>
|
|
11
|
+
<th class="text-left">Trend</th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
<tbody>
|
|
15
|
+
<tr v-for="(product, index) in data" :key="product.id">
|
|
16
|
+
<td>{{ index + 1 }}</td>
|
|
17
|
+
<td>
|
|
18
|
+
<div class="d-flex align-center">
|
|
19
|
+
<v-img :src="product.image" width="50" height="50" class="mr-3" />
|
|
20
|
+
<div>
|
|
21
|
+
<div class="font-weight-bold">{{ product.name }}</div>
|
|
22
|
+
<div class="text-caption">{{ product.category }}</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</td>
|
|
26
|
+
<td>{{ product.sales }}</td>
|
|
27
|
+
<td>
|
|
28
|
+
<v-chip :color="getPositionColor(product.lastWeek, index + 1)" size="small">
|
|
29
|
+
{{ product.lastWeek }}
|
|
30
|
+
</v-chip>
|
|
31
|
+
</td>
|
|
32
|
+
<td>{{ product.peakPosition }}</td>
|
|
33
|
+
<td>{{ product.weeksOnChart }}</td>
|
|
34
|
+
<td>
|
|
35
|
+
<v-icon :color="getTrendColor(product.trend)">{{ getTrendIcon(product.trend) }}</v-icon>
|
|
36
|
+
</td>
|
|
37
|
+
</tr>
|
|
38
|
+
</tbody>
|
|
39
|
+
</v-table>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup>
|
|
43
|
+
defineProps({
|
|
44
|
+
data: Array, // Accepts the chart data
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-table fixed-header>
|
|
3
|
+
<thead>
|
|
4
|
+
<tr>
|
|
5
|
+
<th class="text-left">Position</th>
|
|
6
|
+
<th class="text-left">Product</th>
|
|
7
|
+
<th class="text-left">Sales</th>
|
|
8
|
+
<th class="text-left">Last Week</th>
|
|
9
|
+
<th class="text-left">Peak Position</th>
|
|
10
|
+
<th class="text-left">Weeks on Chart</th>
|
|
11
|
+
<th class="text-left">Trend</th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
<tbody>
|
|
15
|
+
<tr v-for="(product, index) in data" :key="product.id">
|
|
16
|
+
<td>{{ index + 1 }}</td>
|
|
17
|
+
<td>
|
|
18
|
+
<div class="d-flex align-center">
|
|
19
|
+
<v-img :src="product.image" width="50" height="50" class="mr-3" />
|
|
20
|
+
<div>
|
|
21
|
+
<div class="font-weight-bold">{{ product.name }}</div>
|
|
22
|
+
<div class="text-caption">{{ product.category }}</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</td>
|
|
26
|
+
<td>{{ product.sales }}</td>
|
|
27
|
+
<td>
|
|
28
|
+
<v-chip :color="getPositionColor(product.lastWeek, index + 1)" size="small">
|
|
29
|
+
{{ product.lastWeek }}
|
|
30
|
+
</v-chip>
|
|
31
|
+
</td>
|
|
32
|
+
<td>{{ product.peakPosition }}</td>
|
|
33
|
+
<td>{{ product.weeksOnChart }}</td>
|
|
34
|
+
<td>
|
|
35
|
+
<v-icon :color="getTrendColor(product.trend)">{{ getTrendIcon(product.trend) }}</v-icon>
|
|
36
|
+
</td>
|
|
37
|
+
</tr>
|
|
38
|
+
</tbody>
|
|
39
|
+
</v-table>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup>
|
|
43
|
+
defineProps({
|
|
44
|
+
data: Array, // Accepts the chart data
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<!---->
|
|
4
|
+
<v-card elevation="0">
|
|
5
|
+
<v-toolbar :title="chartbar?.name" color="#1F7087">
|
|
6
|
+
<v-dialog min-width="500">
|
|
7
|
+
<template v-slot:activator="{ props: activatorProps }">
|
|
8
|
+
<v-btn v-bind="activatorProps" prepend-icon="fas:fa fa-plus" title="Create a Chart"
|
|
9
|
+
variant="flat">Create a Chart
|
|
10
|
+
</v-btn>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<template v-slot:default="{ isActive }">
|
|
14
|
+
<createchart />
|
|
15
|
+
</template>
|
|
16
|
+
</v-dialog>
|
|
17
|
+
</v-toolbar>
|
|
18
|
+
|
|
19
|
+
<v-tabs v-model="tab" bg-color="#1F7087">
|
|
20
|
+
<div v-for="(menu, index) in chartbar?.menus" :key="index">
|
|
21
|
+
<v-tab :value="menu?.value">{{ menu?.name }}</v-tab>
|
|
22
|
+
</div>
|
|
23
|
+
</v-tabs>
|
|
24
|
+
|
|
25
|
+
<v-card-text>
|
|
26
|
+
<v-tabs-window v-model="tab">
|
|
27
|
+
<v-tabs-window-item value="one">
|
|
28
|
+
<v-row style="padding-top: 15px;">
|
|
29
|
+
<v-col cols="4" v-for="(charts, index) in charts" :key="index">
|
|
30
|
+
<chart :chart="charts" />
|
|
31
|
+
</v-col>
|
|
32
|
+
</v-row>
|
|
33
|
+
</v-tabs-window-item>
|
|
34
|
+
|
|
35
|
+
<v-tabs-window-item value="two">
|
|
36
|
+
<v-row style="padding-top: 15px;">
|
|
37
|
+
<v-col cols="4" v-for="(charts, index) in videocharts" :key="index">
|
|
38
|
+
<chart :chart="charts" />
|
|
39
|
+
</v-col>
|
|
40
|
+
</v-row>
|
|
41
|
+
</v-tabs-window-item>
|
|
42
|
+
|
|
43
|
+
<v-tabs-window-item value="three">
|
|
44
|
+
<v-row style="padding-top: 15px;">
|
|
45
|
+
<v-col cols="4" v-for="(charts, index) in mycharts" :key="index">
|
|
46
|
+
<chart :chart="charts" />
|
|
47
|
+
</v-col>
|
|
48
|
+
</v-row>
|
|
49
|
+
</v-tabs-window-item>
|
|
50
|
+
</v-tabs-window>
|
|
51
|
+
</v-card-text>
|
|
52
|
+
</v-card>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<script setup>
|
|
57
|
+
import chart from './chart/chart.vue'
|
|
58
|
+
import createchart from './chart/add-chart.vue'
|
|
59
|
+
import { ref } from 'vue'
|
|
60
|
+
import {
|
|
61
|
+
useUserStore
|
|
62
|
+
} from '../../../../auth/app/stores/user'
|
|
63
|
+
|
|
64
|
+
const userStore = useUserStore()
|
|
65
|
+
|
|
66
|
+
const tab = ref(null);
|
|
67
|
+
const {
|
|
68
|
+
$directus,
|
|
69
|
+
$readItems,
|
|
70
|
+
$readItem
|
|
71
|
+
} = useNuxtApp()
|
|
72
|
+
|
|
73
|
+
const {
|
|
74
|
+
data: charts
|
|
75
|
+
} = await useAsyncData('charts', () => {
|
|
76
|
+
return $directus.request($readItems('musicchart', {
|
|
77
|
+
fields: ['*', { '*': ['*'] }]
|
|
78
|
+
}))
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const {
|
|
82
|
+
data: videocharts
|
|
83
|
+
} = await useAsyncData('videocharts', () => {
|
|
84
|
+
return $directus.request($readItems('musicchart', {
|
|
85
|
+
filter: {
|
|
86
|
+
type: {
|
|
87
|
+
_eq: "Video"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}))
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const {
|
|
94
|
+
data: mycharts
|
|
95
|
+
} = await useAsyncData('mycharts', () => {
|
|
96
|
+
return $directus.request($readItems('musicchart', {
|
|
97
|
+
filter: {
|
|
98
|
+
creator: {
|
|
99
|
+
_eq: `${userStore?.email?.value}`
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}))
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const {
|
|
106
|
+
data: chartbar
|
|
107
|
+
} = await useAsyncData('chartbar', () => {
|
|
108
|
+
return $directus.request($readItem('navigation', '33'))
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
definePageMeta({
|
|
112
|
+
middleware: ['authenticated'],
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
useHead({
|
|
116
|
+
title: 'Charts',
|
|
117
|
+
})
|
|
118
|
+
</script>
|