@mostfeatured/dbi 0.2.16 → 0.2.18
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/dist/src/types/Components/HTMLComponentsV2/index.d.ts +4 -0
- package/dist/src/types/Components/HTMLComponentsV2/index.d.ts.map +1 -1
- package/dist/src/types/Components/HTMLComponentsV2/index.js +40 -5
- package/dist/src/types/Components/HTMLComponentsV2/index.js.map +1 -1
- package/dist/src/types/Event.d.ts +21 -13
- package/dist/src/types/Event.d.ts.map +1 -1
- package/dist/src/types/Event.js.map +1 -1
- package/dist/test/index.js +1 -1
- package/dist/test/index.js.map +1 -1
- package/generated/namespaceData.d.ts +3 -1
- package/package.json +6 -2
- package/.gitattributes +0 -2
- package/.hintrc +0 -8
- package/.vscode/settings.json +0 -3
- package/docs/ADVANCED_FEATURES.md +0 -840
- package/docs/API_REFERENCE.md +0 -929
- package/docs/CHAT_INPUT.md +0 -811
- package/docs/COMPONENTS.md +0 -1039
- package/docs/EVENTS.md +0 -568
- package/docs/GETTING_STARTED.md +0 -398
- package/docs/LOCALIZATION.md +0 -777
- package/docs/README.md +0 -345
- package/docs/SVELTE_COMPONENTS.md +0 -1111
- package/docs/llm/ADVANCED_FEATURES.txt +0 -521
- package/docs/llm/API_REFERENCE.txt +0 -659
- package/docs/llm/CHAT_INPUT.txt +0 -514
- package/docs/llm/COMPONENTS.txt +0 -595
- package/docs/llm/EVENTS.txt +0 -449
- package/docs/llm/GETTING_STARTED.txt +0 -296
- package/docs/llm/LOCALIZATION.txt +0 -501
- package/docs/llm/README.txt +0 -193
- package/docs/llm/SVELTE_COMPONENTS.txt +0 -566
- package/src/DBI.ts +0 -1007
- package/src/Events.ts +0 -189
- package/src/data/eventMap.json +0 -248
- package/src/index.ts +0 -23
- package/src/methods/handleMessageCommands.ts +0 -482
- package/src/methods/hookEventListeners.ts +0 -119
- package/src/methods/hookInteractionListeners.ts +0 -314
- package/src/methods/publishInteractions.ts +0 -256
- package/src/types/ApplicationRoleConnectionMetadata.ts +0 -19
- package/src/types/Builders/ButtonBuilder.ts +0 -53
- package/src/types/Builders/ChannelSelectMenuBuilder.ts +0 -53
- package/src/types/Builders/MentionableSelectMenuBuilder.ts +0 -53
- package/src/types/Builders/ModalBuilder.ts +0 -53
- package/src/types/Builders/RoleSelectMenuBuilder.ts +0 -53
- package/src/types/Builders/StringSelectMenuBuilder.ts +0 -53
- package/src/types/Builders/UserSelectMenuBuilder.ts +0 -53
- package/src/types/ChatInput/ChatInput.ts +0 -28
- package/src/types/ChatInput/ChatInputOptions.ts +0 -388
- package/src/types/Components/Button.ts +0 -39
- package/src/types/Components/ChannelSelectMenu.ts +0 -43
- package/src/types/Components/HTMLComponentsV2/HTMLComponentsV2Handlers.ts +0 -78
- package/src/types/Components/HTMLComponentsV2/index.ts +0 -761
- package/src/types/Components/HTMLComponentsV2/parser.ts +0 -649
- package/src/types/Components/HTMLComponentsV2/svelteParser.ts +0 -1503
- package/src/types/Components/HTMLComponentsV2/svelteRenderer.ts +0 -416
- package/src/types/Components/MentionableSelectMenu.ts +0 -43
- package/src/types/Components/Modal.ts +0 -46
- package/src/types/Components/RoleSelectMenu.ts +0 -43
- package/src/types/Components/StringSelectMenu.ts +0 -43
- package/src/types/Components/UserSelectMenu.ts +0 -43
- package/src/types/Event.ts +0 -145
- package/src/types/Interaction.ts +0 -100
- package/src/types/other/CustomEvent.ts +0 -19
- package/src/types/other/FakeMessageInteraction.ts +0 -408
- package/src/types/other/InteractionLocale.ts +0 -34
- package/src/types/other/Locale.ts +0 -70
- package/src/types/other/MessageContextMenu.ts +0 -27
- package/src/types/other/UserContextMenu.ts +0 -25
- package/src/utils/MemoryStore.ts +0 -28
- package/src/utils/UtilTypes.ts +0 -11
- package/src/utils/customId.ts +0 -49
- package/src/utils/permissions.ts +0 -5
- package/src/utils/recursiveImport.ts +0 -35
- package/src/utils/recursiveUnload.ts +0 -25
- package/src/utils/unloadModule.ts +0 -7
- package/test/index.ts +0 -176
- package/test/product-showcase.svelte +0 -558
- package/test/test.ts +0 -3
- package/tsconfig.json +0 -51
|
@@ -1,558 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
/// <reference types="@mostfeatured/dbi/svelte" />
|
|
3
|
-
import stuffs from "stuffs";
|
|
4
|
-
import { add } from "./test.js";
|
|
5
|
-
|
|
6
|
-
let {
|
|
7
|
-
products = [],
|
|
8
|
-
currentIndex = 0,
|
|
9
|
-
cart = [],
|
|
10
|
-
view = "browse", // 'browse' | 'cart' | 'details' | 'reviews'
|
|
11
|
-
elapsedTime = 0,
|
|
12
|
-
editingProduct = null, // Product being edited in modal
|
|
13
|
-
reviewText = "", // Review text from modal
|
|
14
|
-
reviews = [], // Array of { productId, productName, rating, review, date }
|
|
15
|
-
selectedCategory = "all", // Category filter
|
|
16
|
-
sortBy = "default", // Sorting option
|
|
17
|
-
} = $props();
|
|
18
|
-
|
|
19
|
-
// Get unique categories from products
|
|
20
|
-
// Note: Uses local variables for SSR template rendering
|
|
21
|
-
function getCategories() {
|
|
22
|
-
const cats = [...new Set(products.map((p) => p.category))];
|
|
23
|
-
return cats;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Filter and sort products
|
|
27
|
-
// Note: Uses local variables for SSR template rendering
|
|
28
|
-
function getFilteredProducts() {
|
|
29
|
-
let filtered = products;
|
|
30
|
-
|
|
31
|
-
// Apply category filter
|
|
32
|
-
if (selectedCategory !== "all") {
|
|
33
|
-
filtered = filtered.filter((p) => p.category === selectedCategory);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Apply sorting
|
|
37
|
-
if (sortBy === "price-low") {
|
|
38
|
-
filtered = [...filtered].sort((a, b) => a.price - b.price);
|
|
39
|
-
} else if (sortBy === "price-high") {
|
|
40
|
-
filtered = [...filtered].sort((a, b) => b.price - a.price);
|
|
41
|
-
} else if (sortBy === "name") {
|
|
42
|
-
filtered = [...filtered].sort((a, b) => a.name.localeCompare(b.name));
|
|
43
|
-
} else if (sortBy === "rating") {
|
|
44
|
-
filtered = [...filtered].sort((a, b) => b.rating - a.rating);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return filtered;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Get current product from filtered list
|
|
51
|
-
// Note: Uses local variables for SSR template rendering
|
|
52
|
-
function getCurrentProduct() {
|
|
53
|
-
const filtered = getFilteredProducts();
|
|
54
|
-
if (filtered.length === 0) return null;
|
|
55
|
-
const idx = Math.min(currentIndex, filtered.length - 1);
|
|
56
|
-
return filtered[idx];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Format elapsed time using stuffs
|
|
60
|
-
function formatTime(seconds) {
|
|
61
|
-
return stuffs.formatSeconds(seconds);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Handle category selection
|
|
65
|
-
function onCategoryChange(ctx) {
|
|
66
|
-
const selected = ctx.interaction.values[0];
|
|
67
|
-
data.selectedCategory = selected;
|
|
68
|
-
data.currentIndex = 0; // Reset to first product when filter changes
|
|
69
|
-
ctx.interaction.deferUpdate();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Handle sort selection
|
|
73
|
-
function onSortChange(ctx) {
|
|
74
|
-
const selected = ctx.interaction.values[0];
|
|
75
|
-
data.sortBy = selected;
|
|
76
|
-
data.currentIndex = 0; // Reset to first product when sort changes
|
|
77
|
-
ctx.interaction.deferUpdate();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function nextProduct() {
|
|
81
|
-
// Get filtered length using data context
|
|
82
|
-
let filtered = data.products || [];
|
|
83
|
-
const category = data.selectedCategory ?? "all";
|
|
84
|
-
if (category !== "all") {
|
|
85
|
-
filtered = filtered.filter((p) => p.category === category);
|
|
86
|
-
}
|
|
87
|
-
const currentIdx = data.currentIndex ?? 0;
|
|
88
|
-
data.currentIndex = (currentIdx + 1) % filtered.length;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function prevProduct() {
|
|
92
|
-
// Get filtered length using data context
|
|
93
|
-
let filtered = data.products || [];
|
|
94
|
-
const category = data.selectedCategory ?? "all";
|
|
95
|
-
if (category !== "all") {
|
|
96
|
-
filtered = filtered.filter((p) => p.category === category);
|
|
97
|
-
}
|
|
98
|
-
const currentIdx = data.currentIndex ?? 0;
|
|
99
|
-
data.currentIndex = (currentIdx - 1 + filtered.length) % filtered.length;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Helper to get current product in handler context
|
|
103
|
-
function getProductInHandler() {
|
|
104
|
-
let filtered = data.products || [];
|
|
105
|
-
const category = data.selectedCategory ?? "all";
|
|
106
|
-
const sort = data.sortBy ?? "default";
|
|
107
|
-
|
|
108
|
-
if (category !== "all") {
|
|
109
|
-
filtered = filtered.filter((p) => p.category === category);
|
|
110
|
-
}
|
|
111
|
-
// Apply sorting
|
|
112
|
-
if (sort === "price-low") {
|
|
113
|
-
filtered = [...filtered].sort((a, b) => a.price - b.price);
|
|
114
|
-
} else if (sort === "price-high") {
|
|
115
|
-
filtered = [...filtered].sort((a, b) => b.price - a.price);
|
|
116
|
-
} else if (sort === "name") {
|
|
117
|
-
filtered = [...filtered].sort((a, b) => a.name.localeCompare(b.name));
|
|
118
|
-
} else if (sort === "rating") {
|
|
119
|
-
filtered = [...filtered].sort((a, b) => b.rating - a.rating);
|
|
120
|
-
}
|
|
121
|
-
if (filtered.length === 0) return null;
|
|
122
|
-
const idx = Math.min(data.currentIndex ?? 0, filtered.length - 1);
|
|
123
|
-
return filtered[idx];
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function addToCart(ctx) {
|
|
127
|
-
const product = getProductInHandler();
|
|
128
|
-
if (!product) return;
|
|
129
|
-
data.cart = [...data.cart, product];
|
|
130
|
-
ctx.interaction.reply({
|
|
131
|
-
content:
|
|
132
|
-
"✅ Added **" +
|
|
133
|
-
product.name +
|
|
134
|
-
"** to cart! (Cart: " +
|
|
135
|
-
data.cart.length +
|
|
136
|
-
" items)",
|
|
137
|
-
flags: ["Ephemeral"],
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function showCart() {
|
|
142
|
-
data.view = "cart";
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function showBrowse() {
|
|
146
|
-
data.view = "browse";
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function showDetails() {
|
|
150
|
-
data.view = "details";
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function showReviews() {
|
|
154
|
-
data.view = "reviews";
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function clearCart(ctx) {
|
|
158
|
-
data.cart = [];
|
|
159
|
-
ctx.interaction.reply({
|
|
160
|
-
content: "🗑️ Cart cleared!",
|
|
161
|
-
flags: ["Ephemeral"],
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function checkout(ctx) {
|
|
166
|
-
if (data.cart.length === 0) {
|
|
167
|
-
ctx.interaction.reply({
|
|
168
|
-
content: "Cart is empty!",
|
|
169
|
-
flags: ["Ephemeral"],
|
|
170
|
-
});
|
|
171
|
-
noRender(); // Cart boşsa UI güncellemeye gerek yok
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const total = data.cart.reduce((sum, p) => sum + p.price, 0);
|
|
175
|
-
ctx.interaction.reply({
|
|
176
|
-
content:
|
|
177
|
-
"💳 **Order Placed!**\\nItems: " +
|
|
178
|
-
data.cart.length +
|
|
179
|
-
"\\nTotal: $" +
|
|
180
|
-
total,
|
|
181
|
-
flags: ["Ephemeral"],
|
|
182
|
-
});
|
|
183
|
-
data.cart = [];
|
|
184
|
-
data.view = "browse";
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Open the review modal for current product
|
|
188
|
-
async function openReviewModal(ctx) {
|
|
189
|
-
// Store which product we're reviewing
|
|
190
|
-
const product = getProductInHandler();
|
|
191
|
-
if (!product) {
|
|
192
|
-
ctx.interaction.reply({
|
|
193
|
-
content: "No product selected!",
|
|
194
|
-
flags: ["Ephemeral"],
|
|
195
|
-
});
|
|
196
|
-
noRender();
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
data.editingProduct = product;
|
|
200
|
-
|
|
201
|
-
// Show the modal and await the response
|
|
202
|
-
const { fields, interaction } = await showModal("review-modal");
|
|
203
|
-
|
|
204
|
-
// Handle the response - rating now comes from string-select as an array
|
|
205
|
-
const ratingArray = fields.rating || ["5"]; // string-select returns array
|
|
206
|
-
const rating = Array.isArray(ratingArray) ? ratingArray[0] : ratingArray;
|
|
207
|
-
const review = fields.review || "";
|
|
208
|
-
|
|
209
|
-
// Add review to the reviews array (use data.reviews for current value after await)
|
|
210
|
-
data.reviews = [
|
|
211
|
-
...data.reviews,
|
|
212
|
-
{
|
|
213
|
-
productId: currentIndex,
|
|
214
|
-
productName: product?.name,
|
|
215
|
-
rating: parseInt(rating),
|
|
216
|
-
review: review,
|
|
217
|
-
date: new Date().toLocaleDateString(),
|
|
218
|
-
},
|
|
219
|
-
];
|
|
220
|
-
|
|
221
|
-
interaction.reply({
|
|
222
|
-
content: `⭐ **Review Submitted!**\n**Product:** ${product?.name}\n**Rating:** ${rating}/5\n**Review:** ${review}`,
|
|
223
|
-
flags: ["Ephemeral"],
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
// Clear editing state
|
|
227
|
-
data.editingProduct = null;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Open quantity modal for adding to cart
|
|
231
|
-
async function openQuantityModal(ctx) {
|
|
232
|
-
const product = getProductInHandler();
|
|
233
|
-
if (!product) {
|
|
234
|
-
ctx.interaction.reply({
|
|
235
|
-
content: "No product selected!",
|
|
236
|
-
flags: ["Ephemeral"],
|
|
237
|
-
});
|
|
238
|
-
noRender();
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
data.editingProduct = product;
|
|
242
|
-
|
|
243
|
-
// Show the modal and await the response
|
|
244
|
-
const { fields, interaction } = await showModal("quantity-modal");
|
|
245
|
-
|
|
246
|
-
const quantity = parseInt(fields.quantity) || 1;
|
|
247
|
-
|
|
248
|
-
// Add multiple of the same product
|
|
249
|
-
for (let i = 0; i < quantity; i++) {
|
|
250
|
-
data.cart = [...data.cart, product];
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
interaction.reply({
|
|
254
|
-
content: `✅ Added **${quantity}x ${product?.name}** to cart! (Cart: ${data.cart.length} items)`,
|
|
255
|
-
flags: ["Ephemeral"],
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
data.editingProduct = null;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
onMount(() => {
|
|
262
|
-
console.log(add(2, 3)); // Test the imported function
|
|
263
|
-
|
|
264
|
-
data.elapsedTime = 0;
|
|
265
|
-
const interval = setInterval(() => {
|
|
266
|
-
// Use lowPriorityUpdate to skip render if a user interaction is in progress
|
|
267
|
-
lowPriorityUpdate(() => {
|
|
268
|
-
data.elapsedTime += 1;
|
|
269
|
-
});
|
|
270
|
-
}, 1000);
|
|
271
|
-
|
|
272
|
-
return () => {
|
|
273
|
-
clearInterval(interval);
|
|
274
|
-
};
|
|
275
|
-
});
|
|
276
|
-
</script>
|
|
277
|
-
|
|
278
|
-
<!-- Main UI Components -->
|
|
279
|
-
<components>
|
|
280
|
-
{#if view === "browse"}
|
|
281
|
-
<container accent-color="5865F2">
|
|
282
|
-
<components>
|
|
283
|
-
<section>
|
|
284
|
-
<components>
|
|
285
|
-
<text-display>## 🛍️ Product Showcase</text-display>
|
|
286
|
-
<text-display
|
|
287
|
-
>**{getCurrentProduct()?.name || "No products"}**
|
|
288
|
-
{getCurrentProduct()?.description || ""}</text-display
|
|
289
|
-
>
|
|
290
|
-
<text-display
|
|
291
|
-
>💰 **\${getCurrentProduct()?.price || 0}**</text-display
|
|
292
|
-
>
|
|
293
|
-
</components>
|
|
294
|
-
<thumbnail media={getCurrentProduct()?.image}></thumbnail>
|
|
295
|
-
</section>
|
|
296
|
-
|
|
297
|
-
<separator></separator>
|
|
298
|
-
|
|
299
|
-
<!-- Category Filter -->
|
|
300
|
-
<action-row>
|
|
301
|
-
<string-select
|
|
302
|
-
placeholder="🏷️ Filter by Category"
|
|
303
|
-
onchange={onCategoryChange}
|
|
304
|
-
>
|
|
305
|
-
<option
|
|
306
|
-
value="all"
|
|
307
|
-
description="Show all products"
|
|
308
|
-
default={selectedCategory === "all"}
|
|
309
|
-
>
|
|
310
|
-
📦 All Categories
|
|
311
|
-
</option>
|
|
312
|
-
{#each getCategories() as cat}
|
|
313
|
-
<option
|
|
314
|
-
value={cat}
|
|
315
|
-
description="Filter by {cat}"
|
|
316
|
-
default={selectedCategory === cat}
|
|
317
|
-
>
|
|
318
|
-
🏷️ {cat}
|
|
319
|
-
</option>
|
|
320
|
-
{/each}
|
|
321
|
-
</string-select>
|
|
322
|
-
</action-row>
|
|
323
|
-
|
|
324
|
-
<!-- Sort Options -->
|
|
325
|
-
<action-row>
|
|
326
|
-
<string-select placeholder="📊 Sort Products" onchange={onSortChange}>
|
|
327
|
-
<option
|
|
328
|
-
value="default"
|
|
329
|
-
description="Original order"
|
|
330
|
-
default={sortBy === "default"}
|
|
331
|
-
>
|
|
332
|
-
📋 Default Order
|
|
333
|
-
</option>
|
|
334
|
-
<option
|
|
335
|
-
value="price-low"
|
|
336
|
-
description="Cheapest first"
|
|
337
|
-
default={sortBy === "price-low"}
|
|
338
|
-
>
|
|
339
|
-
💰 Price: Low to High
|
|
340
|
-
</option>
|
|
341
|
-
<option
|
|
342
|
-
value="price-high"
|
|
343
|
-
description="Most expensive first"
|
|
344
|
-
default={sortBy === "price-high"}
|
|
345
|
-
>
|
|
346
|
-
💎 Price: High to Low
|
|
347
|
-
</option>
|
|
348
|
-
<option
|
|
349
|
-
value="name"
|
|
350
|
-
description="A-Z alphabetically"
|
|
351
|
-
default={sortBy === "name"}
|
|
352
|
-
>
|
|
353
|
-
🔤 Name: A-Z
|
|
354
|
-
</option>
|
|
355
|
-
<option
|
|
356
|
-
value="rating"
|
|
357
|
-
description="Best rated first"
|
|
358
|
-
default={sortBy === "rating"}
|
|
359
|
-
>
|
|
360
|
-
⭐ Rating: Best First
|
|
361
|
-
</option>
|
|
362
|
-
</string-select>
|
|
363
|
-
</action-row>
|
|
364
|
-
|
|
365
|
-
<separator></separator>
|
|
366
|
-
|
|
367
|
-
<text-display
|
|
368
|
-
>📦 Product {currentIndex + 1} of {getFilteredProducts().length} | 🛒 Cart:
|
|
369
|
-
{cart.length}
|
|
370
|
-
items {selectedCategory !== "all"
|
|
371
|
-
? `| 🏷️ ${selectedCategory}`
|
|
372
|
-
: ""}</text-display
|
|
373
|
-
>
|
|
374
|
-
|
|
375
|
-
<action-row>
|
|
376
|
-
<button style="Secondary" onclick={prevProduct}>◀️ Prev</button>
|
|
377
|
-
<button style="Secondary" onclick={nextProduct}>Next ▶️</button>
|
|
378
|
-
<button style="Success" onclick={openQuantityModal}
|
|
379
|
-
>🛒 Add to Cart</button
|
|
380
|
-
>
|
|
381
|
-
<button style="Primary" onclick={showDetails}>📋 Details</button>
|
|
382
|
-
<button style="Primary" onclick={showCart}
|
|
383
|
-
>🛒 View Cart ({cart.length})</button
|
|
384
|
-
>
|
|
385
|
-
</action-row>
|
|
386
|
-
|
|
387
|
-
<action-row>
|
|
388
|
-
<button style="Secondary" onclick={openReviewModal}
|
|
389
|
-
>⭐ Write Review</button
|
|
390
|
-
>
|
|
391
|
-
<button style="Secondary" onclick={showReviews}
|
|
392
|
-
>📝 View Reviews ({reviews.length})</button
|
|
393
|
-
>
|
|
394
|
-
</action-row>
|
|
395
|
-
|
|
396
|
-
<separator></separator>
|
|
397
|
-
<text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
|
|
398
|
-
</components>
|
|
399
|
-
</container>
|
|
400
|
-
{:else if view === "cart"}
|
|
401
|
-
<container accent-color="57F287">
|
|
402
|
-
<components>
|
|
403
|
-
<text-display>## 🛒 Your Cart</text-display>
|
|
404
|
-
|
|
405
|
-
{#if cart.length === 0}
|
|
406
|
-
<text-display>*Your cart is empty*</text-display>
|
|
407
|
-
{:else}
|
|
408
|
-
{#each cart as item, i}
|
|
409
|
-
<text-display>• **{item.name}** - \${item.price}</text-display>
|
|
410
|
-
{/each}
|
|
411
|
-
<separator></separator>
|
|
412
|
-
<text-display
|
|
413
|
-
>**Total: \${cart.reduce(
|
|
414
|
-
(sum, p) => sum + p.price,
|
|
415
|
-
0
|
|
416
|
-
)}**</text-display
|
|
417
|
-
>
|
|
418
|
-
{/if}
|
|
419
|
-
|
|
420
|
-
<action-row>
|
|
421
|
-
<button style="Secondary" onclick={showBrowse}
|
|
422
|
-
>◀️ Back to Browse</button
|
|
423
|
-
>
|
|
424
|
-
<button style="Danger" onclick={clearCart}>🗑️ Clear Cart</button>
|
|
425
|
-
<button style="Success" onclick={checkout}>💳 Checkout</button>
|
|
426
|
-
</action-row>
|
|
427
|
-
|
|
428
|
-
<separator></separator>
|
|
429
|
-
<text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
|
|
430
|
-
</components>
|
|
431
|
-
</container>
|
|
432
|
-
{:else if view === "details"}
|
|
433
|
-
<container accent-color="FEE75C">
|
|
434
|
-
<components>
|
|
435
|
-
<section>
|
|
436
|
-
<components>
|
|
437
|
-
<text-display>## 📋 Product Details</text-display>
|
|
438
|
-
<text-display>**{getCurrentProduct()?.name}**</text-display>
|
|
439
|
-
</components>
|
|
440
|
-
<thumbnail media={getCurrentProduct()?.image}></thumbnail>
|
|
441
|
-
</section>
|
|
442
|
-
|
|
443
|
-
<separator></separator>
|
|
444
|
-
|
|
445
|
-
<text-display
|
|
446
|
-
>### Description
|
|
447
|
-
{getCurrentProduct()?.description}</text-display
|
|
448
|
-
>
|
|
449
|
-
|
|
450
|
-
<separator></separator>
|
|
451
|
-
|
|
452
|
-
<text-display
|
|
453
|
-
>### Specifications • **Category:** {getCurrentProduct()?.category}
|
|
454
|
-
• **Rating:** ⭐ {getCurrentProduct()?.rating}/5 • **Stock:** {getCurrentProduct()
|
|
455
|
-
?.stock} available • **Price:** 💰 **\${getCurrentProduct()
|
|
456
|
-
?.price}**</text-display
|
|
457
|
-
>
|
|
458
|
-
|
|
459
|
-
<action-row>
|
|
460
|
-
<button style="Secondary" onclick={showBrowse}>◀️ Back</button>
|
|
461
|
-
<button style="Success" onclick={openQuantityModal}
|
|
462
|
-
>🛒 Add to Cart</button
|
|
463
|
-
>
|
|
464
|
-
<button style="Secondary" onclick={openReviewModal}
|
|
465
|
-
>⭐ Write Review</button
|
|
466
|
-
>
|
|
467
|
-
</action-row>
|
|
468
|
-
|
|
469
|
-
<separator></separator>
|
|
470
|
-
<text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
|
|
471
|
-
</components>
|
|
472
|
-
</container>
|
|
473
|
-
{:else if view === "reviews"}
|
|
474
|
-
<container accent-color="EB459E">
|
|
475
|
-
<components>
|
|
476
|
-
<text-display>## 📝 Product Reviews</text-display>
|
|
477
|
-
|
|
478
|
-
{#if reviews.length === 0}
|
|
479
|
-
<text-display
|
|
480
|
-
>*No reviews yet. Be the first to write one!*</text-display
|
|
481
|
-
>
|
|
482
|
-
{:else}
|
|
483
|
-
{#each reviews as r, i}
|
|
484
|
-
<text-display
|
|
485
|
-
>**{r.productName}** - {"⭐".repeat(r.rating)}{"☆".repeat(
|
|
486
|
-
5 - r.rating
|
|
487
|
-
)} ({r.rating}/5)
|
|
488
|
-
{r.review ? `> ${r.review}` : ""}
|
|
489
|
-
*{r.date}*</text-display
|
|
490
|
-
>
|
|
491
|
-
{#if i < reviews.length - 1}
|
|
492
|
-
<separator></separator>
|
|
493
|
-
{/if}
|
|
494
|
-
{/each}
|
|
495
|
-
{/if}
|
|
496
|
-
|
|
497
|
-
<separator></separator>
|
|
498
|
-
<text-display>**Total Reviews:** {reviews.length}</text-display>
|
|
499
|
-
|
|
500
|
-
<action-row>
|
|
501
|
-
<button style="Secondary" onclick={showBrowse}
|
|
502
|
-
>◀️ Back to Browse</button
|
|
503
|
-
>
|
|
504
|
-
<button style="Primary" onclick={openReviewModal}
|
|
505
|
-
>⭐ Write Review</button
|
|
506
|
-
>
|
|
507
|
-
</action-row>
|
|
508
|
-
|
|
509
|
-
<separator></separator>
|
|
510
|
-
<text-display>⏱️ Session: {formatTime(elapsedTime)}</text-display>
|
|
511
|
-
</components>
|
|
512
|
-
</container>
|
|
513
|
-
{/if}
|
|
514
|
-
</components>
|
|
515
|
-
|
|
516
|
-
<!-- Review Modal: Now using new Label component structure with String Select -->
|
|
517
|
-
<components
|
|
518
|
-
type="modal"
|
|
519
|
-
id="review-modal"
|
|
520
|
-
title="Write a Review for {editingProduct?.name || 'Product'}"
|
|
521
|
-
>
|
|
522
|
-
<field label="Rating" description="How would you rate this product?">
|
|
523
|
-
<string-select id="rating" placeholder="Select a rating">
|
|
524
|
-
<option value="5" emoji="⭐">5 Stars - Excellent!</option>
|
|
525
|
-
<option value="4" emoji="⭐">4 Stars - Great</option>
|
|
526
|
-
<option value="3" emoji="⭐">3 Stars - Good</option>
|
|
527
|
-
<option value="2" emoji="⭐">2 Stars - Fair</option>
|
|
528
|
-
<option value="1" emoji="⭐">1 Star - Poor</option>
|
|
529
|
-
</string-select>
|
|
530
|
-
</field>
|
|
531
|
-
<field
|
|
532
|
-
label="Your Review"
|
|
533
|
-
description="Share your experience with this product"
|
|
534
|
-
>
|
|
535
|
-
<text-input
|
|
536
|
-
id="review"
|
|
537
|
-
placeholder="Write your detailed review here..."
|
|
538
|
-
style="Paragraph"
|
|
539
|
-
></text-input>
|
|
540
|
-
</field>
|
|
541
|
-
</components>
|
|
542
|
-
|
|
543
|
-
<!-- Quantity Modal: Opens when user clicks "Add to Cart" -->
|
|
544
|
-
<components
|
|
545
|
-
type="modal"
|
|
546
|
-
id="quantity-modal"
|
|
547
|
-
title="Add {editingProduct?.name || 'Product'} to Cart"
|
|
548
|
-
>
|
|
549
|
-
<field label="Quantity" description="How many would you like to add?">
|
|
550
|
-
<text-input
|
|
551
|
-
id="quantity"
|
|
552
|
-
placeholder="Enter quantity (1-10)"
|
|
553
|
-
style="Short"
|
|
554
|
-
value="1"
|
|
555
|
-
required
|
|
556
|
-
></text-input>
|
|
557
|
-
</field>
|
|
558
|
-
</components>
|
package/test/test.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Mapped from https://www.typescriptlang.org/tsconfig
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
// Type Checking
|
|
5
|
-
"allowUnreachableCode": false,
|
|
6
|
-
"allowUnusedLabels": false,
|
|
7
|
-
"noFallthroughCasesInSwitch": true,
|
|
8
|
-
"noImplicitOverride": true,
|
|
9
|
-
"noImplicitReturns": false,
|
|
10
|
-
"strict": false,
|
|
11
|
-
"useUnknownInCatchVariables": true,
|
|
12
|
-
"noUncheckedIndexedAccess": true,
|
|
13
|
-
// Modules
|
|
14
|
-
"module": "commonjs",
|
|
15
|
-
"moduleResolution": "node",
|
|
16
|
-
"resolveJsonModule": true,
|
|
17
|
-
// Emit
|
|
18
|
-
"declaration": true,
|
|
19
|
-
"declarationMap": true,
|
|
20
|
-
"importHelpers": true,
|
|
21
|
-
"inlineSources": true,
|
|
22
|
-
"newLine": "lf",
|
|
23
|
-
"noEmitHelpers": true,
|
|
24
|
-
"outDir": "dist",
|
|
25
|
-
"preserveConstEnums": true,
|
|
26
|
-
"removeComments": false,
|
|
27
|
-
"sourceMap": true,
|
|
28
|
-
"esModuleInterop": true,
|
|
29
|
-
"forceConsistentCasingInFileNames": true,
|
|
30
|
-
// Language and Environment
|
|
31
|
-
"emitDecoratorMetadata": true,
|
|
32
|
-
"experimentalDecorators": true,
|
|
33
|
-
"lib": [
|
|
34
|
-
"ESNext"
|
|
35
|
-
],
|
|
36
|
-
"target": "ESNext",
|
|
37
|
-
"useDefineForClassFields": true,
|
|
38
|
-
"skipLibCheck": true,
|
|
39
|
-
"skipDefaultLibCheck": true,
|
|
40
|
-
// Include DBI Svelte type definitions
|
|
41
|
-
"typeRoots": [
|
|
42
|
-
"./node_modules/@types",
|
|
43
|
-
"./generated"
|
|
44
|
-
]
|
|
45
|
-
},
|
|
46
|
-
"include": [
|
|
47
|
-
"src/**/*",
|
|
48
|
-
"test/**/*",
|
|
49
|
-
"generated/**/*"
|
|
50
|
-
]
|
|
51
|
-
}
|