@meeovi/layer-departments 1.0.0

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.
Files changed (32) hide show
  1. package/app/components/categories/adultstore.vue +123 -0
  2. package/app/components/categories/chart/[id].vue +254 -0
  3. package/app/components/categories/chart/add-chart.vue +142 -0
  4. package/app/components/categories/chart/chart.vue +82 -0
  5. package/app/components/categories/chart/monthlyChart.vue +46 -0
  6. package/app/components/categories/chart/musicchart.vue +35 -0
  7. package/app/components/categories/chart/update-chart.vue +278 -0
  8. package/app/components/categories/chart/weeklyChart.vue +46 -0
  9. package/app/components/categories/chart/yearlyChart.vue +46 -0
  10. package/app/components/categories/charts.vue +118 -0
  11. package/app/components/categories/deals.vue +101 -0
  12. package/app/components/categories/eats.vue +49 -0
  13. package/app/components/categories/restaurants.vue +77 -0
  14. package/app/components/categories/station/[id].vue +72 -0
  15. package/app/components/categories/stations.vue +124 -0
  16. package/app/components/categories/time/features/alarms.vue +276 -0
  17. package/app/components/categories/time/features/bedtime.vue +12 -0
  18. package/app/components/categories/time/features/stopwatch.vue +109 -0
  19. package/app/components/categories/time/features/timer.vue +191 -0
  20. package/app/components/categories/time/time.vue +63 -0
  21. package/app/components/categories/travel.vue +75 -0
  22. package/app/components/categories/weather/weather.vue +44 -0
  23. package/app/components/related/relatedcharts.vue +39 -0
  24. package/app/components/related/short.vue +207 -0
  25. package/app/components/related/space.vue +79 -0
  26. package/app/pages/departments/[...slug].vue +385 -0
  27. package/app/pages/departments/category/[...slug].vue +135 -0
  28. package/dist/nuxt.config.d.ts +2 -0
  29. package/dist/nuxt.config.js +7 -0
  30. package/nuxt.config.ts +11 -0
  31. package/package.json +35 -0
  32. package/tsconfig.json +14 -0
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <div>
3
+ <v-row>
4
+ <v-col>
5
+ <v-card :disabled="loading" :loading="loading" class="mx-auto my-12" max-width="374">
6
+ <template v-slot:loader="{ isActive }">
7
+ <v-progress-linear :active="isActive" color="deep-purple" height="4"
8
+ indeterminate></v-progress-linear>
9
+ </template>
10
+
11
+ <v-img height="250" src="https://cdn.vuetifyjs.com/images/cards/cooking.png" cover></v-img>
12
+
13
+ <v-card-item>
14
+ <v-card-title>Cafe Badilico</v-card-title>
15
+
16
+ <v-card-subtitle>
17
+ <span class="me-1">Local Favorite</span>
18
+
19
+ <v-icon color="error" icon="mdi-fire-circle" size="small"></v-icon>
20
+ </v-card-subtitle>
21
+ </v-card-item>
22
+
23
+ <v-card-text>
24
+ <v-row align="center" class="mx-0">
25
+ <v-rating :model-value="4.5" color="amber" density="compact" size="small" half-increments
26
+ readonly></v-rating>
27
+
28
+ <div class="text-grey ms-4">
29
+ 4.5 (413)
30
+ </div>
31
+ </v-row>
32
+
33
+ <div class="my-4 text-subtitle-1">
34
+ $ • Italian, Cafe
35
+ </div>
36
+
37
+ <div>Small plates, salads & sandwiches - an intimate setting with 12 indoor seats plus patio
38
+ seating.</div>
39
+ </v-card-text>
40
+
41
+ <v-divider class="mx-4 mb-1"></v-divider>
42
+
43
+ <v-card-title>Tonight's availability</v-card-title>
44
+
45
+ <div class="px-4 mb-2">
46
+ <v-chip-group v-model="selection" selected-class="bg-deep-purple-lighten-2">
47
+ <v-chip>5:30PM</v-chip>
48
+
49
+ <v-chip>7:30PM</v-chip>
50
+
51
+ <v-chip>8:00PM</v-chip>
52
+
53
+ <v-chip>9:00PM</v-chip>
54
+ </v-chip-group>
55
+ </div>
56
+
57
+ <v-card-actions>
58
+ <v-btn color="deep-purple-lighten-2" text="Reserve" block border @click="reserve"></v-btn>
59
+ </v-card-actions>
60
+ </v-card>
61
+ </v-col>
62
+ </v-row>
63
+ </div>
64
+ </template>
65
+
66
+ <script setup>
67
+ import { ref } from 'vue'
68
+
69
+ const loading = ref(false)
70
+ const selection = ref(1)
71
+
72
+ function reserve () {
73
+ loading.value = true
74
+
75
+ setTimeout(() => (loading.value = false), 2000)
76
+ }
77
+ </script>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div class="contentPage">
3
+ <v-row>
4
+ <v-col cols="12">
5
+ <v-card color="#b02564">
6
+ <div class="d-flex flex-no-wrap justify-space-between">
7
+ <div>
8
+ <v-card-title class="text-h5">
9
+ {{ station?.name }} <share style="display: inline-block; font-size: 15px;" />
10
+ </v-card-title>
11
+
12
+ <v-card-subtitle>Format: {{ station?.format }}</v-card-subtitle>
13
+
14
+ <v-card-subtitle>Categories:
15
+ <div v-for="category in station?.categories" :key="category">
16
+ {{ category?.categories_id?.name }}
17
+ </div>
18
+ </v-card-subtitle>
19
+
20
+ <v-card-subtitle v-dompurify-html="station?.description"></v-card-subtitle>
21
+ </div>
22
+
23
+ <v-avatar class="ma-3" rounded="0" size="125">
24
+ <NuxtImg :src="`${$directus.url}/assets/${station?.image?.filename_disk}`" />
25
+ </v-avatar>
26
+ </div>
27
+
28
+ <audio :src="`${$directus.url}/assets/${station?.file?.filename_disk}`" controls loop class="radioStation"></audio>
29
+ </v-card>
30
+ </v-col>
31
+
32
+ <v-col cols="12">
33
+ <relatedstations />
34
+ </v-col>
35
+
36
+ <v-col cols="12">
37
+ <comments />
38
+ </v-col>
39
+ </v-row>
40
+ </div>
41
+ </template>
42
+
43
+ <script setup>
44
+ import {
45
+ ref,
46
+ computed
47
+ } from 'vue'
48
+ import relatedstations from '@/components/catalog/product/relatedstations.vue'
49
+ import comments from '~/components/partials/globals/comments.vue'
50
+ import share from '~/components/partials/globals/share.vue'
51
+
52
+ const route = useRoute()
53
+
54
+ const {
55
+ $directus,
56
+ $readItem
57
+ } = useNuxtApp()
58
+
59
+ const {
60
+ data: station
61
+ } = await useAsyncData('station', () => {
62
+ return $directus.request($readItem('radios', route.params.id, {
63
+ fields: ['*', {
64
+ '*': ['*']
65
+ }]
66
+ }))
67
+ })
68
+
69
+ useHead({
70
+ title: computed(() => station?.value?.name || 'Station Page'),
71
+ });
72
+ </script>
@@ -0,0 +1,124 @@
1
+ <template>
2
+ <div>
3
+ <!---->
4
+ <v-card elevation="0">
5
+ <v-toolbar :title="stationbar?.name" color="#b02564">
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 Station"
9
+ variant="flat">Create a Station
10
+ </v-btn>
11
+ </template>
12
+
13
+ <template v-slot:default="{ isActive }">
14
+ <createstation />
15
+ </template>
16
+ </v-dialog>
17
+ </v-toolbar>
18
+
19
+ <v-tabs v-model="tab" bg-color="#b02564">
20
+ <div v-for="(menu, index) in stationbar?.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="6" v-for="(stations, index) in stations" :key="index">
30
+ <station :radio="stations" />
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="6" v-for="(stations, index) in livestations" :key="index">
38
+ <station :radio="stations" />
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="6" v-for="(stations, index) in mystations" :key="index">
46
+ <station :radio="stations" />
47
+ </v-col>
48
+ </v-row>
49
+ </v-tabs-window-item>
50
+ </v-tabs-window>
51
+ </v-card-text>
52
+ </v-card>
53
+
54
+ </div>
55
+ </template>
56
+
57
+ <script setup>
58
+ import station from '../../../../commerce/app/components/catalog/product/radiostation.vue'
59
+ import createstation from '../../../../commerce/app/components/catalog/product/add-station.vue'
60
+ import { ref } from 'vue'
61
+ import {
62
+ useUserStore
63
+ } from '../../../../auth/app/stores/user'
64
+
65
+ const userStore = useUserStore()
66
+
67
+ const tab = ref(null);
68
+ const {
69
+ $directus,
70
+ $readItems,
71
+ $readItem
72
+ } = useNuxtApp()
73
+
74
+ const userDisplayName = computed(() => {
75
+ return userStore.user?.name || userStore.user?.username || 'User'
76
+ })
77
+
78
+ const {
79
+ data: stations
80
+ } = await useAsyncData('stations', () => {
81
+ return $directus.request($readItems('radios', {
82
+ fields: ['*', { '*': ['*'] }]
83
+ }))
84
+ })
85
+
86
+ const {
87
+ data: livestations
88
+ } = await useAsyncData('livestations', () => {
89
+ return $directus.request($readItems('radios', {
90
+ filter: {
91
+ type: {
92
+ _eq: "Live"
93
+ }
94
+ },
95
+ fields: ['*', { '*': ['*'] }]
96
+ }))
97
+ })
98
+
99
+ const {
100
+ data: mystations
101
+ } = await useAsyncData('mystations', () => {
102
+ return $directus.request($readItems('radios', {
103
+ filter: {
104
+ creator: {
105
+ _eq: `${userDisplayName.value}`
106
+ }
107
+ }
108
+ }))
109
+ })
110
+
111
+ const {
112
+ data: stationbar
113
+ } = await useAsyncData('stationbar', () => {
114
+ return $directus.request($readItem('navigation', '34'))
115
+ })
116
+
117
+ definePageMeta({
118
+ middleware: ['authenticated'],
119
+ })
120
+
121
+ useHead({
122
+ title: 'Radio Stations',
123
+ })
124
+ </script>
@@ -0,0 +1,276 @@
1
+ <template>
2
+ <div>
3
+ <v-container>
4
+ <v-row justify="center">
5
+ <v-col cols="12" md="8">
6
+ <v-card class="mb-4">
7
+ <v-card-title class="text-h4 justify-center">
8
+ Alarms
9
+ </v-card-title>
10
+
11
+ <!-- Add New Alarm -->
12
+ <v-card-text>
13
+ <v-row align="center">
14
+ <v-col cols="12" sm="4">
15
+ <v-time-picker v-model="newAlarmTime" format="24hr" class="mt-4"></v-time-picker>
16
+ </v-col>
17
+ <v-col cols="12" sm="8">
18
+ <v-text-field v-model="newAlarmLabel" label="Alarm Label"
19
+ placeholder="Enter alarm description"></v-text-field>
20
+
21
+ <!-- Repeat Days -->
22
+ <v-chip-group v-model="selectedDays" multiple class="mb-4">
23
+ <v-chip v-for="day in weekDays" :key="day.value" :value="day.value" filter>
24
+ {{ day.label }}
25
+ </v-chip>
26
+ </v-chip-group>
27
+
28
+ <v-btn color="primary" @click="addAlarm" :disabled="!newAlarmTime">
29
+ Add Alarm
30
+ </v-btn>
31
+ </v-col>
32
+ </v-row>
33
+ </v-card-text>
34
+ </v-card>
35
+
36
+ <!-- Alarm List -->
37
+ <v-card>
38
+ <v-list>
39
+ <v-list-item v-for="alarm in alarms" :key="alarm.id" class="mb-2">
40
+ <v-list-item-content>
41
+ <v-row align="center">
42
+ <v-col cols="12" sm="4">
43
+ <div class="text-h5">{{ formatTime(alarm.time) }}</div>
44
+ <div class="text-caption">{{ alarm.label }}</div>
45
+ </v-col>
46
+ <v-col cols="12" sm="4">
47
+ <v-chip-group>
48
+ <v-chip v-for="day in alarm.days" :key="day" small label>
49
+ {{ weekDays.find(d => d.value === day).shortLabel }}
50
+ </v-chip>
51
+ </v-chip-group>
52
+ </v-col>
53
+ <v-col cols="12" sm="4" class="text-right">
54
+ <v-switch v-model="alarm.active" @change="toggleAlarm(alarm)"
55
+ color="primary" hide-details inset></v-switch>
56
+ <v-btn icon color="error" @click="deleteAlarm(alarm.id)">
57
+ <v-icon>mdi-delete</v-icon>
58
+ </v-btn>
59
+ </v-col>
60
+ </v-row>
61
+ </v-list-item-content>
62
+ </v-list-item>
63
+ </v-list>
64
+ </v-card>
65
+ </v-col>
66
+ </v-row>
67
+ </v-container>
68
+ </div>
69
+ </template>
70
+
71
+ <script setup>
72
+ import {
73
+ ref,
74
+ onMounted,
75
+ watch
76
+ } from 'vue'
77
+
78
+ useHead({
79
+ title: 'Meeovi Time - Alarms'
80
+ })
81
+
82
+ // State
83
+ const alarms = ref([])
84
+ const newAlarmTime = ref('')
85
+ const newAlarmLabel = ref('')
86
+ const selectedDays = ref([])
87
+
88
+ // Constants
89
+ const weekDays = [{
90
+ value: 0,
91
+ label: 'Sunday',
92
+ shortLabel: 'Sun'
93
+ },
94
+ {
95
+ value: 1,
96
+ label: 'Monday',
97
+ shortLabel: 'Mon'
98
+ },
99
+ {
100
+ value: 2,
101
+ label: 'Tuesday',
102
+ shortLabel: 'Tue'
103
+ },
104
+ {
105
+ value: 3,
106
+ label: 'Wednesday',
107
+ shortLabel: 'Wed'
108
+ },
109
+ {
110
+ value: 4,
111
+ label: 'Thursday',
112
+ shortLabel: 'Thu'
113
+ },
114
+ {
115
+ value: 5,
116
+ label: 'Friday',
117
+ shortLabel: 'Fri'
118
+ },
119
+ {
120
+ value: 6,
121
+ label: 'Saturday',
122
+ shortLabel: 'Sat'
123
+ }
124
+ ]
125
+
126
+ // Methods
127
+ const loadAlarms = () => {
128
+ const savedAlarms = localStorage.getItem('alarms')
129
+ if (savedAlarms) {
130
+ alarms.value = JSON.parse(savedAlarms)
131
+ setupAlarmChecks()
132
+ }
133
+ }
134
+
135
+ const saveAlarms = () => {
136
+ localStorage.setItem('alarms', JSON.stringify(alarms.value))
137
+ }
138
+
139
+ const addAlarm = () => {
140
+ if (!newAlarmTime.value) return
141
+
142
+ const newAlarm = {
143
+ id: Date.now(),
144
+ time: newAlarmTime.value,
145
+ label: newAlarmLabel.value || 'Alarm',
146
+ days: selectedDays.value,
147
+ active: true,
148
+ nextTrigger: calculateNextTrigger(newAlarmTime.value, selectedDays.value)
149
+ }
150
+
151
+ alarms.value.push(newAlarm)
152
+ saveAlarms()
153
+ setupAlarmCheck(newAlarm)
154
+
155
+ // Reset form
156
+ newAlarmTime.value = ''
157
+ newAlarmLabel.value = ''
158
+ selectedDays.value = []
159
+ }
160
+
161
+ const deleteAlarm = (id) => {
162
+ alarms.value = alarms.value.filter(alarm => alarm.id !== id)
163
+ saveAlarms()
164
+ }
165
+
166
+ const toggleAlarm = (alarm) => {
167
+ alarm.active = !alarm.active
168
+ if (alarm.active) {
169
+ alarm.nextTrigger = calculateNextTrigger(alarm.time, alarm.days)
170
+ }
171
+ saveAlarms()
172
+ }
173
+
174
+ const formatTime = (time) => {
175
+ if (!time) return ''
176
+ return time
177
+ }
178
+
179
+ const calculateNextTrigger = (time, days) => {
180
+ const [hours, minutes] = time.split(':')
181
+ const now = new Date()
182
+ const today = now.getDay()
183
+
184
+ let nextDate = new Date()
185
+ nextDate.setHours(parseInt(hours), parseInt(minutes), 0, 0)
186
+
187
+ if (days.length === 0) {
188
+ if (nextDate <= now) {
189
+ nextDate.setDate(nextDate.getDate() + 1)
190
+ }
191
+ return nextDate.getTime()
192
+ }
193
+
194
+ // Find the next day that the alarm should trigger
195
+ let daysUntilNext = 7
196
+ for (const day of days) {
197
+ const diff = (day - today + 7) % 7
198
+ if (diff === 0 && nextDate > now) {
199
+ daysUntilNext = 0
200
+ break
201
+ }
202
+ if (diff < daysUntilNext && (diff > 0 || (diff === 0 && nextDate <= now))) {
203
+ daysUntilNext = diff
204
+ }
205
+ }
206
+
207
+ nextDate.setDate(nextDate.getDate() + daysUntilNext)
208
+ return nextDate.getTime()
209
+ }
210
+
211
+ const setupAlarmChecks = () => {
212
+ alarms.value.forEach(setupAlarmCheck)
213
+ }
214
+
215
+ const setupAlarmCheck = (alarm) => {
216
+ if (!alarm.active) return
217
+
218
+ const checkAlarm = () => {
219
+ const now = Date.now()
220
+ if (now >= alarm.nextTrigger) {
221
+ triggerAlarm(alarm)
222
+ alarm.nextTrigger = calculateNextTrigger(alarm.time, alarm.days)
223
+ saveAlarms()
224
+ }
225
+ }
226
+
227
+ // Check every minute
228
+ setInterval(checkAlarm, 60000)
229
+ }
230
+
231
+ const triggerAlarm = (alarm) => {
232
+ // Play alarm sound
233
+ const audio = new Audio()
234
+ audio.src = '/path/to/alarm-sound.mp3' // Add your alarm sound file
235
+ audio.loop = true
236
+
237
+ // Show notification if supported
238
+ if ('Notification' in window) {
239
+ Notification.requestPermission().then(permission => {
240
+ if (permission === 'granted') {
241
+ const notification = new Notification('Alarm', {
242
+ body: alarm.label,
243
+ icon: '/path/to/alarm-icon.png' // Add your alarm icon
244
+ })
245
+
246
+ // Close notification and stop sound after 1 minute
247
+ setTimeout(() => {
248
+ notification.close()
249
+ audio.pause()
250
+ }, 60000)
251
+ }
252
+ })
253
+ }
254
+
255
+ audio.play().catch(error => console.log('Error playing alarm:', error))
256
+ }
257
+
258
+ // Watch for changes
259
+ watch(alarms, () => {
260
+ saveAlarms()
261
+ }, {
262
+ deep: true
263
+ })
264
+
265
+ // Initialize
266
+ onMounted(() => {
267
+ loadAlarms()
268
+ })
269
+ </script>
270
+
271
+ <style scoped>
272
+ .v-card {
273
+ max-width: 800px;
274
+ margin: auto;
275
+ }
276
+ </style>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ useHead({
10
+ title: 'Meeovi Time - Bedtime'
11
+ })
12
+ </script>
@@ -0,0 +1,109 @@
1
+ <template>
2
+ <div>
3
+ <v-container>
4
+ <v-row justify="center">
5
+ <v-col cols="12" md="6">
6
+ <v-card class="text-center pa-4">
7
+ <v-card-title class="text-h4 justify-center">
8
+ Stopwatch
9
+ </v-card-title>
10
+ <v-card-text>
11
+ <div class="text-h2 my-4">
12
+ {{ hours | zeroPad }}:{{ minutes | zeroPad }}:{{ seconds | zeroPad }}.{{ milliseconds | zeroPad(3) }}
13
+ </div>
14
+ <v-row justify="center" class="mt-4">
15
+ <v-col cols="auto">
16
+ <v-btn color="primary" @click="startTimer" :disabled="isRunning">
17
+ Start
18
+ </v-btn>
19
+ </v-col>
20
+ <v-col cols="auto">
21
+ <v-btn color="warning" @click="pauseTimer" :disabled="!isRunning">
22
+ Pause
23
+ </v-btn>
24
+ </v-col>
25
+ <v-col cols="auto">
26
+ <v-btn color="error" @click="resetTimer">
27
+ Reset
28
+ </v-btn>
29
+ </v-col>
30
+ </v-row>
31
+ <v-list v-if="laps.length" class="mt-4">
32
+ <v-list-item v-for="(lap, index) in laps" :key="index">
33
+ <v-list-item-content>
34
+ Lap {{ index + 1 }}: {{ formatTime(lap) }}
35
+ </v-list-item-content>
36
+ </v-list-item>
37
+ </v-list>
38
+ </v-card-text>
39
+ </v-card>
40
+ </v-col>
41
+ </v-row>
42
+ </v-container>
43
+ </div>
44
+ </template>
45
+
46
+ <script setup>
47
+ import {
48
+ ref,
49
+ computed
50
+ } from 'vue'
51
+
52
+ useHead({
53
+ title: 'Meeovi Time - Stopwatch'
54
+ })
55
+
56
+ const time = ref(0)
57
+ const isRunning = ref(false)
58
+ const timer = ref(null)
59
+ const laps = ref([])
60
+
61
+ const hours = computed(() => Math.floor(time.value / 3600000))
62
+ const minutes = computed(() => Math.floor((time.value % 3600000) / 60000))
63
+ const seconds = computed(() => Math.floor((time.value % 60000) / 1000))
64
+ const milliseconds = computed(() => time.value % 1000)
65
+
66
+ const startTimer = () => {
67
+ if (!isRunning.value) {
68
+ isRunning.value = true
69
+ const startTime = Date.now() - time.value
70
+ timer.value = setInterval(() => {
71
+ time.value = Date.now() - startTime
72
+ }, 10)
73
+ }
74
+ }
75
+
76
+ const pauseTimer = () => {
77
+ isRunning.value = false
78
+ clearInterval(timer.value)
79
+ }
80
+
81
+ const resetTimer = () => {
82
+ pauseTimer()
83
+ time.value = 0
84
+ laps.value = []
85
+ }
86
+
87
+ const addLap = () => {
88
+ laps.value.push(time.value)
89
+ }
90
+
91
+ const formatTime = (timeValue) => {
92
+ const h = Math.floor(timeValue / 3600000)
93
+ const m = Math.floor((timeValue % 3600000) / 60000)
94
+ const s = Math.floor((timeValue % 60000) / 1000)
95
+ const ms = timeValue % 1000
96
+ return `${padZero(h)}:${padZero(m)}:${padZero(s)}.${padZero(ms, 3)}`
97
+ }
98
+
99
+ const padZero = (num, places = 2) => {
100
+ return String(num).padStart(places, '0')
101
+ }
102
+ </script>
103
+
104
+ <style scoped>
105
+ .v-card {
106
+ max-width: 600px;
107
+ margin: auto;
108
+ }
109
+ </style>