seller-dashboard 1.0.1

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 (34) hide show
  1. package/README.md +24 -0
  2. package/app/components/features/attributes.vue +9 -0
  3. package/app/components/features/incentives.vue +9 -0
  4. package/app/components/features/integrations.vue +9 -0
  5. package/app/components/features/media.vue +9 -0
  6. package/app/components/features/products.vue +9 -0
  7. package/app/components/features/reviews.vue +9 -0
  8. package/app/components/features/settings.vue +9 -0
  9. package/app/components/features/spaces.vue +9 -0
  10. package/app/composables/_auth.ts +14 -0
  11. package/app/composables/registry.ts +162 -0
  12. package/app/composables/useSellerOrders.ts +23 -0
  13. package/app/composables/useSellerProducts.ts +33 -0
  14. package/app/composables/useSellerReviews.ts +18 -0
  15. package/app/composables/useSellerShipments.ts +18 -0
  16. package/app/composables/useSellerShops.ts +23 -0
  17. package/app/composables/useSellerSpaces.ts +13 -0
  18. package/app/middleware/seller-only.global.ts +14 -0
  19. package/app/pages/dashboard/index.vue +16 -0
  20. package/app/pages/dashboard/request.vue +18 -0
  21. package/app/pages/index.vue +20 -0
  22. package/app/pages/orders/index.vue +23 -0
  23. package/app/pages/products/[id].vue +53 -0
  24. package/app/pages/products/create.vue +37 -0
  25. package/app/pages/products/index.vue +23 -0
  26. package/app/pages/reviews/index.vue +23 -0
  27. package/app/pages/shipments/index.vue +23 -0
  28. package/app/pages/shops/index.vue +23 -0
  29. package/app/pages/spaces/index.vue +23 -0
  30. package/global.d.ts +12 -0
  31. package/nuxt.config.ts +11 -0
  32. package/package.json +20 -0
  33. package/runtime/register-magento.ts +16 -0
  34. package/tsconfig.json +21 -0
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # Seller Dashboard Layer
2
+
3
+ This layer provides a seller/admin dashboard UI and runtime provider hooks to integrate with e-commerce adapters (for example `adapter-magento`).
4
+
5
+ Key points
6
+ - Register a runtime provider using `registerSellerProviderRuntime(name, provider)` exported from `app/composables/registry.ts`.
7
+ - The UI composables (e.g. `useSellerProducts`, `useSellerOrders`, `useSellerReviews`) call the registered provider; a memory provider is used by default for development.
8
+ - Routes under this layer are protected by a global middleware that only allows users with `seller` or `admin` roles.
9
+
10
+ Owner-scoped operations
11
+ - Composables automatically pass the current seller id (when available) to provider calls so providers can enforce ownership and return only seller-specific data. The helper `getCurrentSellerId()` is available in `app/composables/_auth.ts` and memory provider enforces owner scoping by default.
12
+
13
+ Integration example (Nuxt runtime):
14
+
15
+ ```ts
16
+ import { registerSellerProviderRuntime } from '~~/layers/seller-dashboard/app/composables/registry'
17
+ import { createMagentoSellerAdapter } from 'adapter-magento'
18
+
19
+ registerSellerProviderRuntime('magento', createMagentoSellerAdapter({ /* config */ }))
20
+ ```
21
+
22
+ Next steps
23
+ - Scaffold product/order/review management pages and wire to real adapters.
24
+ - Add tests and CI checks.
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ </script>
@@ -0,0 +1,14 @@
1
+ export function getCurrentSellerId(): string | undefined {
2
+ try {
3
+ const nuxtApp = useNuxtApp() as any
4
+ const authUser = nuxtApp?.$auth?.user ?? undefined
5
+ if (authUser?.id && (authUser.role === 'seller' || (authUser.roles && authUser.roles.includes('seller')))) return authUser.id
6
+
7
+ const stateUser = (useState as any)('authUser')?.value ?? (useState as any)('user')?.value
8
+ if (stateUser?.id && (stateUser.role === 'seller' || (stateUser.roles && stateUser.roles.includes('seller')))) return stateUser.id
9
+
10
+ return undefined
11
+ } catch (e) {
12
+ return undefined
13
+ }
14
+ }
@@ -0,0 +1,162 @@
1
+ export type RequestContext = { sellerId?: string }
2
+
3
+ export type SellerDashboardProvider = {
4
+ // Products
5
+ listProducts?: (params?: any, ctx?: RequestContext) => Promise<any[]>;
6
+ getProduct?: (id: string, ctx?: RequestContext) => Promise<any>;
7
+ createProduct?: (payload: any, ctx?: RequestContext) => Promise<any>;
8
+ updateProduct?: (id: string, payload: any, ctx?: RequestContext) => Promise<any>;
9
+ deleteProduct?: (id: string, ctx?: RequestContext) => Promise<void>;
10
+
11
+ // Orders
12
+ listOrders?: (params?: any, ctx?: RequestContext) => Promise<any[]>;
13
+ getOrder?: (id: string, ctx?: RequestContext) => Promise<any>;
14
+ updateOrderStatus?: (id: string, status: string, ctx?: RequestContext) => Promise<any>;
15
+
16
+ // Reviews
17
+ listReviews?: (params?: any, ctx?: RequestContext) => Promise<any[]>;
18
+ moderateReview?: (id: string, action: 'approve' | 'reject' | 'hide', ctx?: RequestContext) => Promise<any>;
19
+
20
+ // Shops
21
+ listShops?: (params?: any, ctx?: RequestContext) => Promise<any[]>;
22
+ getShop?: (id: string, ctx?: RequestContext) => Promise<any>;
23
+ updateShop?: (id: string, payload: any, ctx?: RequestContext) => Promise<any>;
24
+
25
+ // Spaces
26
+ listSpaces?: (params?: any, ctx?: RequestContext) => Promise<any[]>;
27
+
28
+ // Shipments
29
+ listShipments?: (params?: any, ctx?: RequestContext) => Promise<any[]>;
30
+ updateShipment?: (id: string, payload: any, ctx?: RequestContext) => Promise<any>;
31
+ }
32
+
33
+ let runtimeProvider: SellerDashboardProvider | null = null;
34
+
35
+ export function registerSellerProviderRuntime(name: string, provider: SellerDashboardProvider) {
36
+ // simple registration; future: support multiple named providers
37
+ runtimeProvider = provider;
38
+ }
39
+
40
+ export function getSellerProvider(): SellerDashboardProvider {
41
+ return runtimeProvider ?? memoryProvider;
42
+ }
43
+
44
+ // Minimal in-memory provider useful for development and tests
45
+ const memoryState = {
46
+ products: [] as any[],
47
+ orders: [] as any[],
48
+ reviews: [] as any[],
49
+ shops: [] as any[],
50
+ spaces: [] as any[],
51
+ shipments: [] as any[],
52
+ };
53
+
54
+ const memoryProvider: SellerDashboardProvider = {
55
+ // Products
56
+ async listProducts(params?: any, ctx?: RequestContext) {
57
+ const sellerId = ctx?.sellerId
58
+ if (sellerId) return memoryState.products.filter(p => p.ownerId === sellerId)
59
+ return [...memoryState.products]
60
+ },
61
+ async getProduct(id: string, ctx?: RequestContext) {
62
+ const sellerId = ctx?.sellerId
63
+ const p = memoryState.products.find(p => p.id === id) ?? null
64
+ if (p && sellerId && p.ownerId !== sellerId) return null
65
+ return p
66
+ },
67
+ async createProduct(payload: any, ctx?: RequestContext) {
68
+ const item = { id: String(Date.now()), ownerId: ctx?.sellerId ?? 'unknown', ...payload };
69
+ memoryState.products.push(item);
70
+ return item;
71
+ },
72
+ async updateProduct(id: string, payload: any, ctx?: RequestContext) {
73
+ const idx = memoryState.products.findIndex(p => p.id === id);
74
+ if (idx === -1) return null;
75
+ if (ctx?.sellerId && memoryState.products[idx].ownerId !== ctx.sellerId) return null;
76
+ memoryState.products[idx] = { ...memoryState.products[idx], ...payload };
77
+ return memoryState.products[idx];
78
+ },
79
+ async deleteProduct(id: string, ctx?: RequestContext) {
80
+ memoryState.products = memoryState.products.filter(p => p.id !== id || (ctx?.sellerId && p.ownerId !== ctx.sellerId));
81
+ },
82
+
83
+ // Orders
84
+ async listOrders(params?: any, ctx?: RequestContext) {
85
+ const sellerId = ctx?.sellerId
86
+ if (sellerId) return memoryState.orders.filter(o => o.sellerId === sellerId)
87
+ return [...memoryState.orders]
88
+ },
89
+ async getOrder(id: string, ctx?: RequestContext) {
90
+ const sellerId = ctx?.sellerId
91
+ const o = memoryState.orders.find(o => o.id === id) ?? null
92
+ if (o && sellerId && o.sellerId !== sellerId) return null
93
+ return o
94
+ },
95
+ async updateOrderStatus(id: string, status: string, ctx?: RequestContext) {
96
+ const o = memoryState.orders.find(o => o.id === id);
97
+ if (!o) return null;
98
+ if (ctx?.sellerId && o.sellerId !== ctx.sellerId) return null;
99
+ o.status = status;
100
+ return o;
101
+ },
102
+
103
+ // Reviews
104
+ async listReviews(params?: any, ctx?: RequestContext) {
105
+ const sellerId = ctx?.sellerId
106
+ if (sellerId) return memoryState.reviews.filter(r => r.sellerId === sellerId)
107
+ return [...memoryState.reviews]
108
+ },
109
+ async moderateReview(id: string, action: 'approve' | 'reject' | 'hide', ctx?: RequestContext) {
110
+ const r = memoryState.reviews.find(r => r.id === id);
111
+ if (!r) return null;
112
+ if (ctx?.sellerId && r.sellerId !== ctx.sellerId) return null;
113
+ r.moderation = action;
114
+ return r;
115
+ },
116
+
117
+ // Shops
118
+ async listShops(params?: any, ctx?: RequestContext) {
119
+ const sellerId = ctx?.sellerId
120
+ if (sellerId) return memoryState.shops.filter(s => s.ownerId === sellerId)
121
+ return [...memoryState.shops]
122
+ },
123
+ async getShop(id: string, ctx?: RequestContext) {
124
+ const sellerId = ctx?.sellerId
125
+ const s = memoryState.shops.find(s => s.id === id) ?? null
126
+ if (s && sellerId && s.ownerId !== sellerId) return null
127
+ return s
128
+ },
129
+ async updateShop(id: string, payload: any, ctx?: RequestContext) {
130
+ const idx = memoryState.shops.findIndex(s => s.id === id);
131
+ if (idx === -1) return null;
132
+ if (ctx?.sellerId && memoryState.shops[idx].ownerId !== ctx.sellerId) return null;
133
+ memoryState.shops[idx] = { ...memoryState.shops[idx], ...payload };
134
+ return memoryState.shops[idx];
135
+ },
136
+
137
+ // Spaces
138
+ async listSpaces(params?: any, ctx?: RequestContext) {
139
+ const sellerId = ctx?.sellerId
140
+ if (sellerId) return memoryState.spaces.filter(sp => sp.ownerId === sellerId)
141
+ return [...memoryState.spaces]
142
+ },
143
+
144
+ // Shipments
145
+ async listShipments(params?: any, ctx?: RequestContext) {
146
+ const sellerId = ctx?.sellerId
147
+ if (sellerId) return memoryState.shipments.filter(s => s.sellerId === sellerId)
148
+ return [...memoryState.shipments]
149
+ },
150
+ async updateShipment(id: string, payload: any, ctx?: RequestContext) {
151
+ const s = memoryState.shipments.find(s => s.id === id);
152
+ if (!s) return null;
153
+ if (ctx?.sellerId && s.sellerId !== ctx.sellerId) return null;
154
+ Object.assign(s, payload);
155
+ return s;
156
+ }
157
+ }
158
+
159
+ export default {
160
+ registerSellerProviderRuntime,
161
+ getSellerProvider,
162
+ }
@@ -0,0 +1,23 @@
1
+ import { getSellerProvider } from './registry'
2
+ import { getCurrentSellerId } from './_auth'
3
+
4
+ export function useSellerOrders() {
5
+ const provider = getSellerProvider()
6
+
7
+ async function listOrders(params?: any) {
8
+ const sellerId = getCurrentSellerId()
9
+ return provider.listOrders?.(params, { sellerId }) ?? []
10
+ }
11
+
12
+ async function getOrder(id: string) {
13
+ const sellerId = getCurrentSellerId()
14
+ return provider.getOrder?.(id, { sellerId }) ?? null
15
+ }
16
+
17
+ async function updateOrderStatus(id: string, status: string) {
18
+ const sellerId = getCurrentSellerId()
19
+ return provider.updateOrderStatus?.(id, status, { sellerId })
20
+ }
21
+
22
+ return { listOrders, getOrder, updateOrderStatus }
23
+ }
@@ -0,0 +1,33 @@
1
+ import { getSellerProvider } from './registry'
2
+ import { getCurrentSellerId } from './_auth'
3
+
4
+ export function useSellerProducts() {
5
+ const provider = getSellerProvider()
6
+
7
+ async function listProducts(params?: any) {
8
+ const sellerId = getCurrentSellerId()
9
+ return provider.listProducts?.(params, { sellerId }) ?? []
10
+ }
11
+
12
+ async function getProduct(id: string) {
13
+ const sellerId = getCurrentSellerId()
14
+ return provider.getProduct?.(id, { sellerId }) ?? null
15
+ }
16
+
17
+ async function createProduct(payload: any) {
18
+ const sellerId = getCurrentSellerId()
19
+ return provider.createProduct?.(payload, { sellerId })
20
+ }
21
+
22
+ async function updateProduct(id: string, payload: any) {
23
+ const sellerId = getCurrentSellerId()
24
+ return provider.updateProduct?.(id, payload, { sellerId })
25
+ }
26
+
27
+ async function deleteProduct(id: string) {
28
+ const sellerId = getCurrentSellerId()
29
+ return provider.deleteProduct?.(id, { sellerId })
30
+ }
31
+
32
+ return { listProducts, getProduct, createProduct, updateProduct, deleteProduct }
33
+ }
@@ -0,0 +1,18 @@
1
+ import { getSellerProvider } from './registry'
2
+ import { getCurrentSellerId } from './_auth'
3
+
4
+ export function useSellerReviews() {
5
+ const provider = getSellerProvider()
6
+
7
+ async function listReviews(params?: any) {
8
+ const sellerId = getCurrentSellerId()
9
+ return provider.listReviews?.(params, { sellerId }) ?? []
10
+ }
11
+
12
+ async function moderateReview(id: string, action: 'approve' | 'reject' | 'hide') {
13
+ const sellerId = getCurrentSellerId()
14
+ return provider.moderateReview?.(id, action, { sellerId })
15
+ }
16
+
17
+ return { listReviews, moderateReview }
18
+ }
@@ -0,0 +1,18 @@
1
+ import { getSellerProvider } from './registry'
2
+ import { getCurrentSellerId } from './_auth'
3
+
4
+ export function useSellerShipments() {
5
+ const provider = getSellerProvider()
6
+
7
+ async function listShipments(params?: any) {
8
+ const sellerId = getCurrentSellerId()
9
+ return provider.listShipments?.(params, { sellerId }) ?? []
10
+ }
11
+
12
+ async function updateShipment(id: string, payload: any) {
13
+ const sellerId = getCurrentSellerId()
14
+ return provider.updateShipment?.(id, payload, { sellerId })
15
+ }
16
+
17
+ return { listShipments, updateShipment }
18
+ }
@@ -0,0 +1,23 @@
1
+ import { getSellerProvider } from './registry'
2
+ import { getCurrentSellerId } from './_auth'
3
+
4
+ export function useSellerShops() {
5
+ const provider = getSellerProvider()
6
+
7
+ async function listShops(params?: any) {
8
+ const sellerId = getCurrentSellerId()
9
+ return provider.listShops?.(params, { sellerId }) ?? []
10
+ }
11
+
12
+ async function getShop(id: string) {
13
+ const sellerId = getCurrentSellerId()
14
+ return provider.getShop?.(id, { sellerId }) ?? null
15
+ }
16
+
17
+ async function updateShop(id: string, payload: any) {
18
+ const sellerId = getCurrentSellerId()
19
+ return provider.updateShop?.(id, payload, { sellerId })
20
+ }
21
+
22
+ return { listShops, getShop, updateShop }
23
+ }
@@ -0,0 +1,13 @@
1
+ import { getSellerProvider } from './registry'
2
+ import { getCurrentSellerId } from './_auth'
3
+
4
+ export function useSellerSpaces() {
5
+ const provider = getSellerProvider()
6
+
7
+ async function listSpaces(params?: any) {
8
+ const sellerId = getCurrentSellerId()
9
+ return provider.listSpaces?.(params, { sellerId }) ?? []
10
+ }
11
+
12
+ return { listSpaces }
13
+ }
@@ -0,0 +1,14 @@
1
+ export default defineNuxtRouteMiddleware((to, from) => {
2
+ // Try a few common places for the current user so the middleware is flexible
3
+ const nuxtApp = useNuxtApp()
4
+ const user = (nuxtApp as any).$auth?.user ?? (useState as any)('authUser')?.value ?? (useState as any)('user')?.value
5
+
6
+ if (!user) {
7
+ return navigateTo('/login')
8
+ }
9
+
10
+ const roles: string[] = user.role ? [user.role] : user.roles ?? []
11
+ if (!roles.includes('seller') && !roles.includes('admin')) {
12
+ return navigateTo('/')
13
+ }
14
+ })
@@ -0,0 +1,16 @@
1
+ <template v-if="profile.role === 'seller'">
2
+ <div>
3
+
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+
9
+ definePageMeta({
10
+ middleware: ['seller']
11
+ })
12
+
13
+ useHead({
14
+ title: "Seller Dashboard - Meeovi"
15
+ })
16
+ </script>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <div v-if="!user.isSeller">
3
+ <p>Your seller account is pending approval.</p>
4
+ <v-btn v-if="!user.profile?.seller_requested" @click="requestSeller">
5
+ Request Seller Access
6
+ </v-btn>
7
+ </div>
8
+ </template>
9
+
10
+ <script setup>
11
+ const user = useUserStore()
12
+
13
+ const requestSeller = async () => {
14
+ await $fetch('/api/seller/request', {
15
+ method: 'POST'
16
+ })
17
+ }
18
+ </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <div class="seller-dashboard">
3
+ <h1>Seller Dashboard</h1>
4
+ <nav>
5
+ <ul>
6
+ <li><NuxtLink to="/seller-dashboard/products">Products</NuxtLink></li>
7
+ <li><NuxtLink to="/seller-dashboard/orders">Orders</NuxtLink></li>
8
+ <li><NuxtLink to="/seller-dashboard/reviews">Reviews</NuxtLink></li>
9
+ <li><NuxtLink to="/seller-dashboard/shops">Shops</NuxtLink></li>
10
+ <li><NuxtLink to="/seller-dashboard/shipments">Shipments</NuxtLink></li>
11
+ </ul>
12
+ </nav>
13
+ <section>
14
+ <p>Use the links to manage your store. Backend adapters (e.g. adapter-magento) can register at runtime.</p>
15
+ </section>
16
+ </div>
17
+ </template>
18
+
19
+ <script setup>
20
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <h2>Orders</h2>
4
+ <button @click="refresh">Refresh</button>
5
+ <ul>
6
+ <li v-for="o in orders" :key="o.id">Order #{{ o.id }} — {{ o.status }}</li>
7
+ </ul>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { ref, onMounted } from 'vue'
13
+ import { useSellerOrders } from '~/layers/seller-dashboard/app/composables/useSellerOrders'
14
+
15
+ const orders = ref([])
16
+ const { listOrders } = useSellerOrders()
17
+
18
+ async function refresh() {
19
+ orders.value = await listOrders()
20
+ }
21
+
22
+ onMounted(refresh)
23
+ </script>
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <div>
3
+ <h2>Edit Product</h2>
4
+ <div v-if="loading">Loading...</div>
5
+ <form v-else @submit.prevent="onSubmit">
6
+ <div>
7
+ <label>Name</label>
8
+ <input v-model="form.name" />
9
+ </div>
10
+ <div>
11
+ <label>Price</label>
12
+ <input v-model.number="form.price" type="number" />
13
+ </div>
14
+ <div>
15
+ <label>Description</label>
16
+ <textarea v-model="form.description" />
17
+ </div>
18
+ <button type="submit">Save</button>
19
+ </form>
20
+ </div>
21
+ </template>
22
+
23
+ <script setup>
24
+ import { reactive, ref, onMounted } from 'vue'
25
+ import { useRoute, useRouter } from '#imports'
26
+ import { useSellerProducts } from '~/layers/seller-dashboard/app/composables/useSellerProducts'
27
+
28
+ const route = useRoute()
29
+ const router = useRouter()
30
+ const { getProduct, updateProduct } = useSellerProducts()
31
+ const loading = ref(true)
32
+ const form = reactive({ name: '', price: 0, description: '' })
33
+
34
+ async function load() {
35
+ loading.value = true
36
+ const id = route.params.id as string
37
+ const p = await getProduct(id)
38
+ if (p) {
39
+ form.name = p.title || p.name || ''
40
+ form.price = p.price || 0
41
+ form.description = p.description || ''
42
+ }
43
+ loading.value = false
44
+ }
45
+
46
+ async function onSubmit() {
47
+ const id = route.params.id as string
48
+ await updateProduct(id, { title: form.name, price: form.price, description: form.description })
49
+ await router.push('/seller-dashboard/products')
50
+ }
51
+
52
+ onMounted(load)
53
+ </script>
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div>
3
+ <h2>Create Product</h2>
4
+ <form @submit.prevent="onSubmit">
5
+ <div>
6
+ <label>Name</label>
7
+ <input v-model="form.name" />
8
+ </div>
9
+ <div>
10
+ <label>Price</label>
11
+ <input v-model.number="form.price" type="number" />
12
+ </div>
13
+ <div>
14
+ <label>Description</label>
15
+ <textarea v-model="form.description" />
16
+ </div>
17
+ <button type="submit">Create</button>
18
+ </form>
19
+ </div>
20
+ </template>
21
+
22
+ <script setup>
23
+ import { reactive } from 'vue'
24
+ import { useRouter } from '#imports'
25
+ import { useSellerProducts } from '~/layers/seller-dashboard/app/composables/useSellerProducts'
26
+
27
+ const form = reactive({ name: '', price: 0, description: '' })
28
+ const { createProduct } = useSellerProducts()
29
+ const router = useRouter()
30
+
31
+ async function onSubmit() {
32
+ const created = await createProduct({ title: form.name, price: form.price, description: form.description })
33
+ if (created && created.id) {
34
+ await router.push(`/seller-dashboard/products/${created.id}`)
35
+ }
36
+ }
37
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <h2>Products</h2>
4
+ <button @click="refresh">Refresh</button>
5
+ <ul>
6
+ <li v-for="p in products" :key="p.id">{{ p.title || p.name || p.id }}</li>
7
+ </ul>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { ref, onMounted } from 'vue'
13
+ import { useSellerProducts } from '~/layers/seller-dashboard/app/composables/useSellerProducts'
14
+
15
+ const products = ref([])
16
+ const { listProducts } = useSellerProducts()
17
+
18
+ async function refresh() {
19
+ products.value = await listProducts()
20
+ }
21
+
22
+ onMounted(refresh)
23
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <h2>Reviews</h2>
4
+ <button @click="refresh">Refresh</button>
5
+ <ul>
6
+ <li v-for="r in reviews" :key="r.id">{{ r.author || r.id }} — {{ r.rating || '' }} — {{ r.content || '' }}</li>
7
+ </ul>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { ref, onMounted } from 'vue'
13
+ import { useSellerReviews } from '~/layers/seller-dashboard/app/composables/useSellerReviews'
14
+
15
+ const reviews = ref([])
16
+ const { listReviews } = useSellerReviews()
17
+
18
+ async function refresh() {
19
+ reviews.value = await listReviews()
20
+ }
21
+
22
+ onMounted(refresh)
23
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <h2>Shipments</h2>
4
+ <button @click="refresh">Refresh</button>
5
+ <ul>
6
+ <li v-for="s in shipments" :key="s.id">Shipment #{{ s.id }} — {{ s.status }}</li>
7
+ </ul>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { ref, onMounted } from 'vue'
13
+ import { useSellerShipments } from '~/layers/seller-dashboard/app/composables/useSellerShipments'
14
+
15
+ const shipments = ref([])
16
+ const { listShipments } = useSellerShipments()
17
+
18
+ async function refresh() {
19
+ shipments.value = await listShipments()
20
+ }
21
+
22
+ onMounted(refresh)
23
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <h2>Shops</h2>
4
+ <button @click="refresh">Refresh</button>
5
+ <ul>
6
+ <li v-for="s in shops" :key="s.id">{{ s.name || s.id }}</li>
7
+ </ul>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { ref, onMounted } from 'vue'
13
+ import { useSellerShops } from '~/layers/seller-dashboard/app/composables/useSellerShops'
14
+
15
+ const shops = ref([])
16
+ const { listShops } = useSellerShops()
17
+
18
+ async function refresh() {
19
+ shops.value = await listShops()
20
+ }
21
+
22
+ onMounted(refresh)
23
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <h2>Spaces</h2>
4
+ <button @click="refresh">Refresh</button>
5
+ <ul>
6
+ <li v-for="sp in spaces" :key="sp.id">{{ sp.name || sp.id }}</li>
7
+ </ul>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { ref, onMounted } from 'vue'
13
+ import { useSellerSpaces } from '~/layers/seller-dashboard/app/composables/useSellerSpaces'
14
+
15
+ const spaces = ref([])
16
+ const { listSpaces } = useSellerSpaces()
17
+
18
+ async function refresh() {
19
+ spaces.value = await listSpaces()
20
+ }
21
+
22
+ onMounted(refresh)
23
+ </script>
package/global.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ declare function useNuxtApp(): any
2
+ declare function useState<T=any>(key: string): { value: T | undefined }
3
+ declare function defineNuxtRouteMiddleware(fn: (to: any, from: any) => any): any
4
+ declare function navigateTo(path: string): any
5
+ declare function useRouter(): any
6
+ declare function useRoute(): any
7
+
8
+ declare module '*.vue' {
9
+ import type { DefineComponent } from 'vue'
10
+ const component: DefineComponent<{}, {}, any>
11
+ export default component
12
+ }
package/nuxt.config.ts ADDED
@@ -0,0 +1,11 @@
1
+ import {
2
+ defineNuxtConfig
3
+ } from 'nuxt/config'
4
+
5
+ export default defineNuxtConfig({
6
+ $meta: {
7
+ name: 'dashboard',
8
+ },
9
+
10
+ runtimeConfig: {}
11
+ })
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "seller-dashboard",
3
+ "version": "1.0.1",
4
+ "description": "Seller dashboard for Meeovi platform",
5
+ "main": "./nuxt.config.ts",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": ["seller", "dashboard", "meeovi"],
10
+ "author": "Meeovi",
11
+ "license": "MIT",
12
+ "type": "module",
13
+ "devDependencies": {
14
+ "nuxt": "^4.3.0"
15
+ },
16
+ "dependencies": {
17
+ "nuxt-charts": "^2.1.1",
18
+ "typescript": "^5.9.3"
19
+ }
20
+ }
@@ -0,0 +1,16 @@
1
+ // Example runtime registration for an adapter-magento style adapter.
2
+ // This file demonstrates how to register a Magento-backed provider at app startup.
3
+ import { registerSellerProviderRuntime } from '../app/composables/registry'
4
+
5
+ // Example factory signature expected from an adapter package
6
+ type MagentoAdapterFactory = (opts: any) => any
7
+
8
+ export function registerMagentoAdapter(factory: MagentoAdapterFactory, opts: any) {
9
+ const adapter = factory(opts)
10
+ registerSellerProviderRuntime('magento', adapter)
11
+ }
12
+
13
+ // Usage (Nuxt runtime):
14
+ // import { registerMagentoAdapter } from '~~/layers/seller-dashboard/runtime/register-magento'
15
+ // import { createMagentoSellerAdapter } from 'adapter-magento'
16
+ // registerMagentoAdapter(createMagentoSellerAdapter, { url: process.env.MAGENTO_URL })
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "declaration": true,
4
+ "emitDeclarationOnly": false,
5
+ "outDir": "dist",
6
+ "moduleResolution": "bundler",
7
+ "module": "ESNext",
8
+ "target": "ESNext",
9
+ "strict": true,
10
+ "jsx": "react-jsx",
11
+ "skipLibCheck": true,
12
+ "noEmitOnError": false
13
+ }
14
+ ,
15
+ "include": [
16
+ "src/**/*",
17
+ "app/**/*",
18
+ "index.ts",
19
+ "package.json"
20
+ , "global.d.ts" ]
21
+ }