update deps & hotfix errors

Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
pakintada@gmail.com 2026-06-16 15:15:34 +07:00
parent dc215addb4
commit a95e7bbb13
7 changed files with 124 additions and 71 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -44,7 +44,7 @@
"prettier-plugin-svelte": "^3.5.1", "prettier-plugin-svelte": "^3.5.1",
"prettier-plugin-tailwindcss": "^0.7.2", "prettier-plugin-tailwindcss": "^0.7.2",
"storybook": "^10.3.5", "storybook": "^10.3.5",
"svelte": "^5.55.2", "svelte": "^5.56.3",
"svelte-adapter-bun": "^1.0.1", "svelte-adapter-bun": "^1.0.1",
"svelte-check": "^4.4.6", "svelte-check": "^4.4.6",
"svelte-sonner": "^1.1.0", "svelte-sonner": "^1.1.0",

View file

@ -83,12 +83,12 @@
errors: [] errors: []
}); });
handleIncomingMessages( // handleIncomingMessages(
JSON.stringify({ // JSON.stringify({
type: 'chat', // type: 'chat',
payload: `${new Date().toLocaleTimeString()}: ${get(authStore)?.displayName} has connected to ${boxid}` // payload: `${new Date().toLocaleTimeString()}: ${get(authStore)?.displayName} has connected to ${boxid}`
}) // })
); // );
} else { } else {
machineStatus = 'Instance lost, try disconnect and re-connect again'; machineStatus = 'Instance lost, try disconnect and re-connect again';
toast.error('Unexpected Error'); toast.error('Unexpected Error');
@ -221,12 +221,12 @@
connectDeviceOk = false; connectDeviceOk = false;
handleIncomingMessages( // handleIncomingMessages(
JSON.stringify({ // JSON.stringify({
type: 'chat', // type: 'chat',
payload: `${new Date().toLocaleTimeString()}: ${get(authStore)?.displayName} has disconnected!` // payload: `${new Date().toLocaleTimeString()}: ${get(authStore)?.displayName} has disconnected!`
}) // })
); // );
} }
function checkDeviceConnection() { function checkDeviceConnection() {

View file

@ -59,16 +59,16 @@ async function handleAdbPayload(raw_payload: string) {
} }
if (raw_payload.startsWith('save_recipe_machine')) { if (raw_payload.startsWith('save_recipe_machine')) {
handleIncomingMessages( // handleIncomingMessages(
JSON.stringify({ // JSON.stringify({
type: 'ui_action', // type: 'ui_action',
payload: { // payload: {
action: uiAction, // action: uiAction,
from: 'brew', // from: 'brew',
ref: `${pd}.${action}` // ref: `${pd}.${action}`
} // }
}) // })
); // );
} }
} else if (raw_payload.startsWith('state')) { } else if (raw_payload.startsWith('state')) {
let res = raw_payload.split('/'); let res = raw_payload.split('/');

View file

@ -465,7 +465,7 @@
await loadAvailableProductCodes(); await loadAvailableProductCodes();
// Enter room to get lock // Enter room to get lock
const entered = enterRoom(country, catalog); const entered = await enterRoom(country, catalog);
if (entered) { if (entered) {
addNotification(`INFO:Entered ${getCatalogDisplayName(catalog)} for adding menu`); addNotification(`INFO:Entered ${getCatalogDisplayName(catalog)} for adding menu`);
@ -815,13 +815,15 @@
<button <button
type="button" type="button"
onclick={() => selectCode(item.code)} onclick={() => selectCode(item.code)}
class="flex w-full items-center justify-between rounded-lg border bg-card p-3 text-left transition-colors hover:border-primary/50 hover:bg-primary/5 {item.isNew ? 'border-green-500/50 bg-green-500/5' : ''}" class="flex w-full items-center justify-between rounded-lg border bg-card p-3 text-left transition-colors hover:border-primary/50 hover:bg-primary/5 {item.isNew
? 'border-green-500/50 bg-green-500/5'
: ''}"
> >
<div class="min-w-0 flex-1"> <div class="min-w-0 flex-1">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="font-mono text-sm">{item.code}</span> <span class="font-mono text-sm">{item.code}</span>
{#if item.isNew} {#if item.isNew}
<Badge class="bg-green-600 hover:bg-green-600 text-[10px] px-1.5 py-0">NEW</Badge> <Badge class="bg-green-600 px-1.5 py-0 text-[10px] hover:bg-green-600">NEW</Badge>
{/if} {/if}
</div> </div>
{#if item.name} {#if item.name}

View file

@ -158,7 +158,8 @@
const primaryLanguageKey = columnConfig.primaryLanguage; const primaryLanguageKey = columnConfig.primaryLanguage;
const primaryLanguageColumn = languageColumnMap[primaryLanguageKey] ?? languageColumnMap.en ?? 3; const primaryLanguageColumn = languageColumnMap[primaryLanguageKey] ?? languageColumnMap.en ?? 3;
const secondaryLanguageKey = primaryLanguageKey === 'en' ? 'th' : 'en'; const secondaryLanguageKey = primaryLanguageKey === 'en' ? 'th' : 'en';
const secondaryLanguageColumn = languageColumnMap[secondaryLanguageKey] ?? languageColumnMap.en ?? 3; const secondaryLanguageColumn =
languageColumnMap[secondaryLanguageKey] ?? languageColumnMap.en ?? 3;
function getCatalogDisplayName(catalogName: string): string { function getCatalogDisplayName(catalogName: string): string {
const match = catalogName.match(/page_catalog_group_(\w+)\.skt/); const match = catalogName.match(/page_catalog_group_(\w+)\.skt/);
@ -797,7 +798,11 @@
} }
// Get all prices for an item (hot, cold, blend) // Get all prices for an item (hot, cold, blend)
function getItemPrices(item: any): { hot: string | null; cold: string | null; blend: string | null } { function getItemPrices(item: any): {
hot: string | null;
cold: string | null;
blend: string | null;
} {
return { return {
hot: getItemPrice(item, 'hot'), hot: getItemPrice(item, 'hot'),
cold: getItemPrice(item, 'cold'), cold: getItemPrice(item, 'cold'),
@ -807,18 +812,23 @@
// Price edit dialog state // Price edit dialog state
let priceEditDialogOpen = $state(false); let priceEditDialogOpen = $state(false);
let priceEditData = $state<{ code: string; type: string; price: string; row: number; col: number; isNew: boolean }[]>([]); let priceEditData = $state<
{ code: string; type: string; price: string; row: number; col: number; isNew: boolean }[]
>([]);
let savingPrice = $state(false); let savingPrice = $state(false);
// Get price info for a single product code // Get price info for a single product code
function getPriceInfoForCode(productCode: string): { price: string; row: number; col: number } | null { function getPriceInfoForCode(
productCode: string
): { price: string; row: number; col: number } | null {
const priceCells = sheetPrices[productCode]; const priceCells = sheetPrices[productCode];
if (!priceCells || priceCells.length === 0) return null; if (!priceCells || priceCells.length === 0) return null;
const headers = get(sheetPriceHeader)[countryCode]; const headers = get(sheetPriceHeader)[countryCode];
if (!headers || headers.length === 0) return null; if (!headers || headers.length === 0) return null;
const headerNames = PRICE_HEADER_NAMES_BY_COUNTRY[countryCode] || PRICE_HEADER_NAMES_BY_COUNTRY.default; const headerNames =
PRICE_HEADER_NAMES_BY_COUNTRY[countryCode] || PRICE_HEADER_NAMES_BY_COUNTRY.default;
const colIdx = findHeaderIndex(headers, headerNames.cash_price); const colIdx = findHeaderIndex(headers, headerNames.cash_price);
if (colIdx < 0) return null; if (colIdx < 0) return null;
@ -848,7 +858,14 @@
function openPriceEditDialog() { function openPriceEditDialog() {
if (!editingItem) return; if (!editingItem) return;
const data: { code: string; type: string; price: string; row: number; col: number; isNew: boolean }[] = []; const data: {
code: string;
type: string;
price: string;
row: number;
col: number;
isNew: boolean;
}[] = [];
for (const code of editingItem.product_codes || []) { for (const code of editingItem.product_codes || []) {
const info = getPriceInfoForCode(code); const info = getPriceInfoForCode(code);
@ -869,7 +886,10 @@
// Save price changes from dialog // Save price changes from dialog
async function handleSavePricesFromDialog() { async function handleSavePricesFromDialog() {
const updates: { row_index: number; cells: { value: string; coord: { row: number; col: number } }[] }[] = []; const updates: {
row_index: number;
cells: { value: string; coord: { row: number; col: number } }[];
}[] = [];
const newPrices: { cells: string[] }[] = []; const newPrices: { cells: string[] }[] = [];
// Get all rows data for duplicate handling // Get all rows data for duplicate handling
@ -877,7 +897,8 @@
// Get header for this country to build cells array correctly // Get header for this country to build cells array correctly
const priceHeaders = get(sheetPriceHeader)[countryCode] || []; const priceHeaders = get(sheetPriceHeader)[countryCode] || [];
const headerNames = PRICE_HEADER_NAMES_BY_COUNTRY[countryCode] || PRICE_HEADER_NAMES_BY_COUNTRY.default; const headerNames =
PRICE_HEADER_NAMES_BY_COUNTRY[countryCode] || PRICE_HEADER_NAMES_BY_COUNTRY.default;
const priceColIdx = findHeaderIndex(priceHeaders, headerNames.cash_price); const priceColIdx = findHeaderIndex(priceHeaders, headerNames.cash_price);
for (const item of priceEditData) { for (const item of priceEditData) {
@ -887,7 +908,7 @@
if (item.price && item.price.trim()) { if (item.price && item.price.trim()) {
// Build cells array based on header structure // Build cells array based on header structure
// Find column indices from header // Find column indices from header
const nameColIdx = priceHeaders.findIndex(h => h.toLowerCase() === 'name') + 1; const nameColIdx = priceHeaders.findIndex((h) => h.toLowerCase() === 'name') + 1;
// Create cells array with correct length // Create cells array with correct length
const cells: string[] = new Array(priceHeaders.length).fill(''); const cells: string[] = new Array(priceHeaders.length).fill('');
@ -936,20 +957,24 @@
for (const rowEntry of rowsForCode) { for (const rowEntry of rowsForCode) {
updates.push({ updates.push({
row_index: rowEntry.row, row_index: rowEntry.row,
cells: [{ cells: [
value: item.price, {
coord: { row: rowEntry.row, col: item.col } value: item.price,
}] coord: { row: rowEntry.row, col: item.col }
}
]
}); });
} }
} else if (item.row) { } else if (item.row) {
// Single row - use the original logic // Single row - use the original logic
updates.push({ updates.push({
row_index: item.row, row_index: item.row,
cells: [{ cells: [
value: item.price, {
coord: { row: item.row, col: item.col } value: item.price,
}] coord: { row: item.row, col: item.col }
}
]
}); });
} }
} }
@ -966,12 +991,12 @@
// Send updates for existing prices // Send updates for existing prices
if (updates.length > 0) { if (updates.length > 0) {
updateSent = updateSheetPrice(country, updates); updateSent = await updateSheetPrice(country, updates);
} }
// Send adds for new prices // Send adds for new prices
if (newPrices.length > 0) { if (newPrices.length > 0) {
addSent = addSheetPrice(country, newPrices); addSent = await addSheetPrice(country, newPrices);
} }
if (updateSent && addSent) { if (updateSent && addSent) {
@ -1457,8 +1482,8 @@
// Step 2: Request menu data (this triggers streaming) // Step 2: Request menu data (this triggers streaming)
// Small delay to ensure enter request is processed first // Small delay to ensure enter request is processed first
setTimeout(() => { setTimeout(async () => {
const requested = requestCatalogMenu(country, catalog); const requested = await requestCatalogMenu(country, catalog);
if (requested) { if (requested) {
console.log('[Edit] Requested menu data via WebSocket'); console.log('[Edit] Requested menu data via WebSocket');
} else { } else {
@ -1653,7 +1678,11 @@
recipe: recipe01_query recipe: recipe01_query
})); }));
console.log('[Edit] Loaded', Object.keys(recipe01_query).length, 'recipes from machine'); console.log(
'[Edit] Loaded',
Object.keys(recipe01_query).length,
'recipes from machine'
);
break; break;
} }
} catch (parseError) { } catch (parseError) {
@ -1965,13 +1994,21 @@
<div class="flex items-center gap-4"> <div class="flex items-center gap-4">
<div class="flex flex-wrap gap-4 text-sm"> <div class="flex flex-wrap gap-4 text-sm">
{#if displayPrices.hot} {#if displayPrices.hot}
<span><span class="text-muted-foreground">Hot</span> {displayPrices.hot}</span> <span
><span class="text-muted-foreground">Hot</span> {displayPrices.hot}</span
>
{/if} {/if}
{#if displayPrices.cold} {#if displayPrices.cold}
<span><span class="text-muted-foreground">Cold</span> {displayPrices.cold}</span> <span
><span class="text-muted-foreground">Cold</span>
{displayPrices.cold}</span
>
{/if} {/if}
{#if displayPrices.blend} {#if displayPrices.blend}
<span><span class="text-muted-foreground">Blend</span> {displayPrices.blend}</span> <span
><span class="text-muted-foreground">Blend</span>
{displayPrices.blend}</span
>
{/if} {/if}
</div> </div>
<Button <Button
@ -2113,7 +2150,13 @@
<!-- View Mode --> <!-- View Mode -->
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-4"> <div class="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-4">
{#each visibleMenuItems as item, index (item.row_index)} {#each visibleMenuItems as item, index (item.row_index)}
<Card.Root class="group relative transition-shadow hover:shadow-md {newlyAddedRowIndices.has(item.row_index) ? 'ring-2 ring-green-500' : ''}"> <Card.Root
class="group relative transition-shadow hover:shadow-md {newlyAddedRowIndices.has(
item.row_index
)
? 'ring-2 ring-green-500'
: ''}"
>
<Card.Content class="flex min-h-[340px] flex-col items-center p-5 text-center"> <Card.Content class="flex min-h-[340px] flex-col items-center p-5 text-center">
<!-- NEW badge for newly added items --> <!-- NEW badge for newly added items -->
{#if newlyAddedRowIndices.has(item.row_index)} {#if newlyAddedRowIndices.has(item.row_index)}
@ -2194,13 +2237,19 @@
{#if prices.hot || prices.cold || prices.blend} {#if prices.hot || prices.cold || prices.blend}
<div class="mt-3 flex w-full justify-center gap-3 text-sm"> <div class="mt-3 flex w-full justify-center gap-3 text-sm">
{#if prices.hot} {#if prices.hot}
<span title="Hot"><span class="text-muted-foreground">Hot</span> {prices.hot}</span> <span title="Hot"
><span class="text-muted-foreground">Hot</span> {prices.hot}</span
>
{/if} {/if}
{#if prices.cold} {#if prices.cold}
<span title="Cold"><span class="text-muted-foreground">Cold</span> {prices.cold}</span> <span title="Cold"
><span class="text-muted-foreground">Cold</span> {prices.cold}</span
>
{/if} {/if}
{#if prices.blend} {#if prices.blend}
<span title="Blend"><span class="text-muted-foreground">Blend</span> {prices.blend}</span> <span title="Blend"
><span class="text-muted-foreground">Blend</span> {prices.blend}</span
>
{/if} {/if}
</div> </div>
{/if} {/if}
@ -2610,15 +2659,21 @@
<div class="max-h-[400px] space-y-3 overflow-y-auto py-4"> <div class="max-h-[400px] space-y-3 overflow-y-auto py-4">
{#each priceEditData as item, index} {#each priceEditData as item, index}
<div class="flex items-center gap-3 rounded-lg border p-3 {item.isNew ? 'border-amber-500/50 bg-amber-500/5' : 'bg-muted/30'}"> <div
<div class="flex-1 min-w-0"> class="flex items-center gap-3 rounded-lg border p-3 {item.isNew
? 'border-amber-500/50 bg-amber-500/5'
: 'bg-muted/30'}"
>
<div class="min-w-0 flex-1">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<Badge variant="outline" class="text-xs"> <Badge variant="outline" class="text-xs">
{item.type} {item.type}
</Badge> </Badge>
<span class="font-mono text-sm truncate">{item.code}</span> <span class="truncate font-mono text-sm">{item.code}</span>
{#if item.isNew} {#if item.isNew}
<Badge class="bg-amber-600 hover:bg-amber-600 text-[10px] px-1.5 py-0">NO PRICE</Badge> <Badge class="bg-amber-600 px-1.5 py-0 text-[10px] hover:bg-amber-600"
>NO PRICE</Badge
>
{/if} {/if}
</div> </div>
</div> </div>
@ -2635,16 +2690,12 @@
{/each} {/each}
{#if priceEditData.length === 0} {#if priceEditData.length === 0}
<div class="py-8 text-center text-muted-foreground"> <div class="py-8 text-center text-muted-foreground">No product codes found</div>
No product codes found
</div>
{/if} {/if}
</div> </div>
<div class="flex justify-end gap-3"> <div class="flex justify-end gap-3">
<Button variant="outline" onclick={() => (priceEditDialogOpen = false)}> <Button variant="outline" onclick={() => (priceEditDialogOpen = false)}>Cancel</Button>
Cancel
</Button>
<Button onclick={handleSavePricesFromDialog} disabled={savingPrice}> <Button onclick={handleSavePricesFromDialog} disabled={savingPrice}>
{#if savingPrice} {#if savingPrice}
<Spinner class="mr-2 h-4 w-4" /> <Spinner class="mr-2 h-4 w-4" />

View file

@ -143,12 +143,12 @@
errors: [] errors: []
}); });
handleIncomingMessages( // handleIncomingMessages(
JSON.stringify({ // JSON.stringify({
type: 'chat', // type: 'chat',
payload: `${new Date().toLocaleTimeString()}: ${get(authStore)?.displayName} has connected to ${boxid}` // payload: `${new Date().toLocaleTimeString()}: ${get(authStore)?.displayName} has connected to ${boxid}`
}) // })
); // );
} else { } else {
addNotification('ERROR:Failed to get machine info'); addNotification('ERROR:Failed to get machine info');
} }