feat: migrate recipe editor

- using eventbus in recipe editor
- migrate to logging instead of console log
- fix case swap not saved, value not update after change, topping slot bug

Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
pakintada@gmail.com 2026-06-19 17:27:28 +07:00
parent 270faf6b34
commit f0619c5a10
65 changed files with 1600 additions and 557 deletions

View file

@ -1,8 +1,9 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { goto } from '$app/navigation';
import { page } from '$app/state';
console.log('error on authed page route, ', page);
logger.info('error on authed page route, ', page);
setTimeout(() => {
goto('/entry');

View file

@ -1,5 +1,6 @@
<!-- navbar select menus -->
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import favicon from '$lib/assets/favicon.svg';
import AppAccountSelect from '$lib/components/app-account-select.svelte';
import AppSidebar from '$lib/components/app-sidebar.svelte';
@ -91,7 +92,7 @@
return false;
}
} catch (e) {
console.error('error on auto connect brew page', e);
logger.error('error on auto connect brew page', e);
addNotification('ERROR:Failed to auto connect, please try again');
}
}
@ -107,7 +108,7 @@
if (websocketConnectedForUid !== currentUser.uid) {
websocketConnectedForUid = currentUser.uid;
console.log('connect ws after auth ready');
logger.info('connect ws after auth ready');
void currentUser.getIdToken(true).then(async (idToken) => {
await connectToWebsocket(idToken);

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { goto } from '$app/navigation';
import { page } from '$app/state';
import { auth, authInitialized } from '$lib/core/stores/auth';
@ -51,7 +52,7 @@
}
})
.catch((error) => {
console.error('Error checking admin status:', error);
logger.error('Error checking admin status:', error);
goto('/dashboard');
});
}

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { onMount } from 'svelte';
import { getRoleDefinitions, buildAvailablePermissions } from '$lib/core/admin/adminService';
import { rolesConfig, rolesLoading, availablePermissions } from '$lib/core/admin/adminStore';
@ -25,7 +26,7 @@
rolesConfig.set(roles);
availablePermissions.set(perms);
} catch (error) {
console.error('Error loading roles:', error);
logger.error('Error loading roles:', error);
} finally {
rolesLoading.set(false);
}

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import * as Card from '$lib/components/ui/card/index';
import * as Dialog from '$lib/components/ui/dialog/index';
import Button from '$lib/components/ui/button/button.svelte';
@ -104,7 +105,7 @@
dialogOpen = false;
onUpdate();
} catch (error) {
console.error('Error updating role:', error);
logger.error('Error updating role:', error);
addNotification('ERROR:Failed to update role');
} finally {
saving = false;

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { onMount } from 'svelte';
import {
getDocumentPermissions,
@ -29,7 +30,7 @@
toolsPerms = tools;
allowedDomains = domains;
} catch (error) {
console.error('Error loading settings:', error);
logger.error('Error loading settings:', error);
} finally {
loading = false;
}

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { onMount } from 'svelte';
import { getAllUsers } from '$lib/core/admin/adminService';
import { adminUsers, usersLoading, adminError } from '$lib/core/admin/adminStore';
@ -16,7 +17,7 @@
const users = await getAllUsers();
adminUsers.set(users);
} catch (error) {
console.error('Error loading users:', error);
logger.error('Error loading users:', error);
adminError.set('Failed to load users');
} finally {
usersLoading.set(false);

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import * as Sheet from '$lib/components/ui/sheet/index';
import Button from '$lib/components/ui/button/button.svelte';
import Label from '$lib/components/ui/label/label.svelte';
@ -141,7 +142,7 @@
addNotification('SUCCESS:User updated successfully');
editSheetOpen.set(false);
} catch (error) {
console.error('Error updating user:', error);
logger.error('Error updating user:', error);
addNotification('ERROR:Failed to update user');
} finally {
saving = false;
@ -157,7 +158,7 @@
try {
availablePermissions = await buildAvailablePermissions();
} catch (error) {
console.error('Error loading permissions:', error);
logger.error('Error loading permissions:', error);
}
loadingPermissions = false;
});

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { asset } from '$app/paths';
import { permission as currentPerms } from '$lib/core/stores/permissions';
import { page } from '$app/stores';
@ -22,7 +23,7 @@
else setCookieOnNonBrowser('department', cnt);
addNotification(`INFO:Selected ${cnt}`);
setTimeout(async () => {
console.log(get(departmentStore));
logger.info(get(departmentStore));
departmentStore.set(cnt);
if (refPage === 'priceslot') {

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import RecipeModuleBtn from '$lib/assets/modules/recipe_btn.png';
import MachineInspectBtn from '$lib/assets/modules/monitoring_btn.png';
import SheetModuleBtn from '$lib/assets/modules/sheet_btn.png';
@ -40,7 +41,7 @@
onMount(() => {
return currentPermissions.subscribe((perm) => {
console.log('sub get perm', JSON.stringify(perm));
logger.info('sub get perm', JSON.stringify(perm));
if (perm.length > 0) {
perms = perm;
}

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { onMount } from 'svelte';
import Button from '$lib/components/ui/button/button.svelte';
import { Input } from '$lib/components/ui/input';
@ -220,7 +221,7 @@
addNotification(`INFO:Recipe loaded from ${recipePath}`);
return;
} catch (error) {
console.error('failed to parse recipe json', recipePath, error);
logger.error('failed to parse recipe json', recipePath, error);
addNotification(`ERR:Invalid recipe JSON from ${recipePath}`);
}
}
@ -348,7 +349,7 @@
if (materialIndex < 0) setNextAvailableId();
showMaterialForm = false;
} catch (error: any) {
console.error('failed to save material', error);
logger.error('failed to save material', error);
addNotification(`ERR:Failed to save material: ${error?.message ?? error}`);
} finally {
saving = false;
@ -427,7 +428,7 @@
deleteConfirmOpen = false;
pendingDeleteMaterial = null;
} catch (error: any) {
console.error('failed to delete material', error);
logger.error('failed to delete material', error);
addNotification(`ERR:Failed to delete material: ${error?.message ?? error}`);
} finally {
saving = false;

View file

@ -1,10 +1,11 @@
import { logger } from '$lib/core/utils/logger';
import { getRecipes } from '$lib/core/client/server';
import { recipeData } from '$lib/core/stores/recipeStore';
import { get } from 'svelte/store';
export async function load({ cookies, params }) {
let dep = cookies.get('department');
console.log('load recipe ', dep, params);
logger.info('load recipe ', dep, params);
let recipes = await getRecipes();
recipes = get(recipeData);

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import Button, { buttonVariants } from '$lib/components/ui/button/button.svelte';
import Input from '$lib/components/ui/input/input.svelte';
import { SearchIcon, RefreshCcw } from '@lucide/svelte/icons';
@ -92,7 +93,7 @@
const recipeFetchInterval = setInterval(async () => {
// schedule check if recipe is empty
if (data.recipes.length == 0) {
console.log('loading recipe ....');
logger.info('loading recipe ....');
// recipeLoading.set(true);
// empty
await getRecipes();

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { onMount } from 'svelte';
import Button from '$lib/components/ui/button/button.svelte';
import { Input } from '$lib/components/ui/input';
@ -230,7 +231,7 @@
addNotification(`INFO:Recipe loaded from ${recipePath}`);
return;
} catch (error) {
console.error('failed to parse recipe json', recipePath, error);
logger.error('failed to parse recipe json', recipePath, error);
addNotification(`ERR:Invalid recipe JSON from ${recipePath}`);
}
}
@ -379,7 +380,7 @@
listDialogOpen = false;
if (index < 0) setNextListId();
} catch (error: any) {
console.error('failed to save topping list', error);
logger.error('failed to save topping list', error);
addNotification(`ERR:Failed to save topping list: ${error?.message ?? error}`);
} finally {
saving = false;
@ -415,7 +416,7 @@
groupDialogOpen = false;
if (index < 0) setNextGroupId();
} catch (error: any) {
console.error('failed to save topping group', error);
logger.error('failed to save topping group', error);
addNotification(`ERR:Failed to save topping group: ${error?.message ?? error}`);
} finally {
saving = false;
@ -522,7 +523,7 @@
deleteConfirmOpen = false;
pendingDelete = null;
} catch (error: any) {
console.error('failed to delete topping', error);
logger.error('failed to delete topping', error);
addNotification(`ERR:Failed to delete topping: ${error?.message ?? error}`);
} finally {
saving = false;

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { onMount, onDestroy } from 'svelte';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
@ -141,7 +142,7 @@
}
}
} catch (e) {
console.error('Failed to load staged menus:', e);
logger.error('Failed to load staged menus:', e);
}
// 3. Load from machine recipes (via recipeFromMachineQuery store)
@ -411,7 +412,7 @@
const key = `sheet.newlyAdded.${country}.${catalog}`;
sessionStorage.setItem(key, JSON.stringify({ timestamp: Date.now(), pending: true }));
} catch (e) {
console.warn('Failed to store newly added marker:', e);
logger.warn('Failed to store newly added marker:', e);
}
// Go back to edit page after successful add
@ -440,7 +441,7 @@
const currentSize = $existingProductCodes.size;
if (currentSize > 0 && currentSize !== previousCodeCount) {
previousCodeCount = currentSize;
console.log('[Add] existingProductCodes updated, reloading available codes:', currentSize);
logger.info('[Add] existingProductCodes updated, reloading available codes:', currentSize);
loadAvailableProductCodes();
}
});
@ -456,7 +457,7 @@
try {
boxid = (await adb.pull('/sdcard/coffeevending/.bid')) || undefined;
} catch (e) {
console.warn('Failed to get boxid from machine:', e);
logger.warn('Failed to get boxid from machine:', e);
}
}
requestListMenu(country, boxid);

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { onMount, onDestroy } from 'svelte';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
@ -331,7 +332,7 @@
name_desc_v2: item.name_desc_v2
});
} catch (error) {
console.error('[Parse] Error parsing menu item:', error, item);
logger.error('[Parse] Error parsing menu item:', error, item);
}
}
@ -720,13 +721,13 @@
}
return;
} catch (error) {
console.error('Failed to parse recipe JSON:', error);
logger.error('Failed to parse recipe JSON:', error);
}
}
addNotification('ERR:Cannot load recipe from machine');
} catch (error) {
console.error('Failed to load preview:', error);
logger.error('Failed to load preview:', error);
addNotification('ERR:Failed to load preview');
} finally {
previewLoading = false;
@ -927,7 +928,7 @@
cells[priceColIdx - 1] = item.price;
}
console.log('[Edit] Building new price row:', {
logger.info('[Edit] Building new price row:', {
code: item.code,
priceColIdx,
nameColIdx,
@ -1206,12 +1207,12 @@
await adb.push(androidPath, file.content);
pushProgress = { current: i + 1, total: filesToPush.length };
console.log(`[GenLayout] Pushed ${i + 1}/${filesToPush.length}: ${androidPath}`);
logger.info(`[GenLayout] Pushed ${i + 1}/${filesToPush.length}: ${androidPath}`);
}
addNotification(`INFO:Pushed ${filesToPush.length} layout files to Android`);
} catch (error) {
console.error('[GenLayout] Push error:', error);
logger.error('[GenLayout] Push error:', error);
addNotification(`ERR:Failed to push files: ${error}`);
} finally {
pushingToAndroid = false;
@ -1242,14 +1243,14 @@
await adb.push(androidPath, file.content);
pushProgress = { current: i + 1, total: files.length };
console.log(`[GenLayout] Pushed ${i + 1}/${files.length}: ${androidPath}`);
logger.info(`[GenLayout] Pushed ${i + 1}/${files.length}: ${androidPath}`);
}
addNotification(`INFO:Pushed ${files.length} layout files to Android`);
openRestartDialog('push-complete');
} catch (error) {
console.error('[GenLayout] Push error:', error);
logger.error('[GenLayout] Push error:', error);
addNotification(`ERR:Failed to push files: ${error}`);
} finally {
pushingToAndroid = false;
@ -1288,7 +1289,7 @@
restartDialogOpen = false;
restartDialogSource = 'manual';
} catch (error) {
console.error('[GenLayout] Restart error:', error);
logger.error('[GenLayout] Restart error:', error);
addNotification(`ERR:Failed to restart app: ${error}`);
} finally {
restarting = false;
@ -1365,7 +1366,7 @@
}
}
} catch (e) {
console.warn('[Edit] Failed to load newly added marker:', e);
logger.warn('[Edit] Failed to load newly added marker:', e);
}
}
@ -1384,7 +1385,7 @@
sessionStorage.removeItem(key);
}
} catch (e) {
console.warn('[Edit] Failed to read previous max row index:', e);
logger.warn('[Edit] Failed to read previous max row index:', e);
}
// Find items with row_index higher than previous max (truly new items)
@ -1397,13 +1398,13 @@
if (newIndices.length > 0) {
newlyAddedRowIndices = new Set(newIndices);
console.log('[Edit] Detected newly added items at row_indices:', newIndices);
logger.info('[Edit] Detected newly added items at row_indices:', newIndices);
// Clear after 60 seconds
setTimeout(() => {
newlyAddedRowIndices = new Set();
}, 60000);
} else {
console.log('[Edit] No new items detected (previousMax:', previousMaxRowIndex, ')');
logger.info('[Edit] No new items detected (previousMax:', previousMaxRowIndex, ')');
}
}
@ -1420,7 +1421,7 @@
const unsubData = sheetData.subscribe((data) => {
if (data.length > 0) {
menuItems = parseMenuItems(data);
console.log(`[Edit] Parsed ${menuItems.length} menu items from WebSocket stream`);
logger.info(`[Edit] Parsed ${menuItems.length} menu items from WebSocket stream`);
}
});
unsubscribers.push(unsubData);
@ -1428,7 +1429,7 @@
// Subscribe to streamMeta for completion status
const unsubMeta = sheetStreamMeta.subscribe((meta) => {
if (meta?.status === 'complete') {
console.log('[Edit] Stream complete, total items:', meta.total_items);
logger.info('[Edit] Stream complete, total items:', meta.total_items);
// Detect newly added item if we're coming back from add page
detectNewlyAddedItem();
@ -1443,7 +1444,7 @@
}
}
if (allCodes.length > 0) {
console.log('[Edit] Requesting prices for', allCodes.length, 'product codes');
logger.info('[Edit] Requesting prices for', allCodes.length, 'product codes');
requestSheetPrice(country, allCodes);
}
} else if (meta?.status === 'error') {
@ -1485,7 +1486,7 @@
setTimeout(async () => {
const requested = await requestCatalogMenu(country, catalog);
if (requested) {
console.log('[Edit] Requested menu data via WebSocket');
logger.info('[Edit] Requested menu data via WebSocket');
} else {
addNotification('ERR:Failed to request menu data');
sheetLoading.set(false);
@ -1500,7 +1501,7 @@
})();
// Data will arrive via WebSocket streaming through sheetStore
console.log('[Edit] Waiting for data via WebSocket streaming...');
logger.info('[Edit] Waiting for data via WebSocket streaming...');
});
// Exit room on unmount
@ -1633,7 +1634,7 @@
const key = `sheet.maxRowIndex.${country}.${catalog}`;
sessionStorage.setItem(key, String(maxRowIndex));
} catch (e) {
console.warn('[Edit] Failed to store max row index:', e);
logger.warn('[Edit] Failed to store max row index:', e);
}
addMenuLoading = true;
@ -1678,7 +1679,7 @@
recipe: recipe01_query
}));
console.log(
logger.info(
'[Edit] Loaded',
Object.keys(recipe01_query).length,
'recipes from machine'
@ -1686,11 +1687,11 @@
break;
}
} catch (parseError) {
console.warn('[Edit] Failed to parse recipe JSON from', recipePath, parseError);
logger.warn('[Edit] Failed to parse recipe JSON from', recipePath, parseError);
}
}
} catch (e) {
console.warn('[Edit] Failed to load machine recipe:', e);
logger.warn('[Edit] Failed to load machine recipe:', e);
}
}
} finally {

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { auth } from '$lib/core/stores/auth';
import { addNotification } from '$lib/core/stores/noti';
import Button from '$lib/components/ui/button/button.svelte';
@ -108,7 +109,7 @@
AdbInstance.instance ? 'INFO:Machine connected' : 'WARN:No machine selected'
);
} catch (error) {
console.error('[Adv] connect error:', error);
logger.error('[Adv] connect error:', error);
addNotification(`ERR:Connect failed: ${error instanceof Error ? error.message : 'unknown'}`);
} finally {
connecting = false;
@ -318,7 +319,7 @@
addNotification(`INFO:Pushed ${success} video(s) to machine (${targetDir})`);
}
} catch (error) {
console.error('[Adv] push to machine error:', error);
logger.error('[Adv] push to machine error:', error);
addNotification(`ERR:Push error: ${error instanceof Error ? error.message : 'unknown'}`);
} finally {
pushingToMachine = false;
@ -389,7 +390,7 @@
} catch (error) {
files[index].status = 'error';
files[index].error = error instanceof Error ? error.message : 'Unknown error';
console.error(`Upload error for ${item.file.name}:`, error);
logger.error(`Upload error for ${item.file.name}:`, error);
}
}
@ -429,7 +430,7 @@
await uploadManifestText(text, uid, displayName, email);
addNotification(`INFO:Manifest uploaded (${active.length} active file(s))`);
} catch (error) {
console.error('[Adv] selected manifest error:', error);
logger.error('[Adv] selected manifest error:', error);
addNotification(`ERR:Manifest failed: ${error instanceof Error ? error.message : 'unknown'}`);
} finally {
generatingManifest = false;
@ -522,7 +523,7 @@
addNotification(`INFO:Machine adv folder synced (${targets.length} file(s))`);
return true;
} catch (error) {
console.error('[Adv] machine sync error:', error);
logger.error('[Adv] machine sync error:', error);
addNotification(`ERR:Machine sync failed: ${error instanceof Error ? error.message : 'unknown'}`);
return false;
} finally {
@ -567,7 +568,7 @@
}
addNotification('INFO:Manifest (from machine) uploaded to server');
} catch (error) {
console.error('[Adv] machine manifest error:', error);
logger.error('[Adv] machine manifest error:', error);
addNotification(`ERR:Machine manifest failed: ${error instanceof Error ? error.message : 'unknown'}`);
} finally {
generatingManifest = false;

View file

@ -1,4 +1,6 @@
<script lang="ts">
import { logger } from '$lib/core/utils/logger';
import Button from '$lib/components/ui/button/button.svelte';
import Spinner from '$lib/components/ui/spinner/spinner.svelte';
import * as Dialog from '$lib/components/ui/dialog/index.js';
@ -71,7 +73,7 @@
// clear out event
GlobalEventBus.on('recipe-event', (d: any) => {
console.log('[recipe-ev] get event: ', d);
logger.info('[recipe-ev] get event: ', d);
if (d?.type == 'load-recipe' && d?.status == 'end') {
addNotification('INFO:Get data, waiting for reloading ...');
// load finish
@ -81,13 +83,13 @@
if (recipeRaw) {
devRecipe = recipeRaw;
// update material & topping
console.log('check dev recipe', devRecipe);
logger.info('check dev recipe', devRecipe);
}
// data.recipes = r01Q.recipe;
buildOverviewForBrewing();
console.log('refresh by m2 mem recipe data done');
logger.info('refresh by m2 mem recipe data done');
recipeLoading = false;
addNotification('INFO:Load recipe from memories success!');
@ -110,7 +112,7 @@
let instance = adb.getAdbInstance();
// recipeFromMachineLoading.set(true);
referenceFromPage.set('brew');
console.log('check instance', instance);
logger.info('check instance', instance);
if (instance) {
recipeLoading = true;
@ -129,7 +131,7 @@
}
} else {
try {
console.log('instance passed!');
logger.info('instance passed!');
const recipePaths = [
`${sourceDir}/cfg/recipe_branch_dev.json`,
`${sourceDir}/coffeethai02.json`
@ -137,7 +139,7 @@
for (const recipePath of recipePaths) {
const dev_recipe = await pullTextWithRetry(recipePath);
console.log('dev recipe pull result', {
logger.info('dev recipe pull result', {
recipePath,
loaded: dev_recipe != undefined,
size: dev_recipe?.length ?? 0
@ -149,7 +151,7 @@
buildOverviewForBrewing();
return;
} catch (error) {
console.error('failed to parse recipe json', recipePath, error);
logger.error('failed to parse recipe json', recipePath, error);
addNotification(`ERROR:Invalid recipe JSON from ${recipePath}`);
}
}
@ -276,7 +278,7 @@
return false;
}
} catch (e) {
console.error('error on auto connect brew page', e);
logger.error('error on auto connect brew page', e);
addNotification('ERROR:Failed to auto connect, please try again');
}
}
@ -349,7 +351,7 @@
}
afterNavigate(async () => {
console.log('after navigate brew');
logger.info('after navigate brew');
await startFetchRecipeFromMachine();
});
@ -577,7 +579,7 @@
)
);
} catch (error) {
console.error('failed to persist staged menus to Android', error);
logger.error('failed to persist staged menus to Android', error);
addNotification('WARN:Failed to save draft menus to Android');
}
}
@ -612,7 +614,7 @@
buildOverviewForBrewing();
return true;
} catch (error) {
console.error('failed to load staged menus from Android', error);
logger.error('failed to load staged menus from Android', error);
addNotification('WARN:Failed to load draft menus from Android');
return false;
}
@ -796,7 +798,18 @@
persistStagedMenus();
clearMenuSaveState(productCode);
addNotification(`INFO:Menu saved: ${productCode}`);
// Sync devRecipe from recipeFromMachine before rebuild —
// the dialog's save handler may have updated recipeFromMachine
// with user edits, and we want buildOverviewForBrewing() to
// use the latest data rather than stale devRecipe.
const latest = get(recipeFromMachine);
if (latest) {
devRecipe = latest;
}
buildOverviewForBrewing();
refresh_counter += 1;
}
onMount(() => {

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import Button from '$lib/components/ui/button/button.svelte';
import Input from '$lib/components/ui/input/input.svelte';
import Label from '$lib/components/ui/label/label.svelte';
@ -338,7 +339,7 @@
addNotification('INFO:Recipe loaded');
return;
} catch (error) {
console.error('failed to parse recipe json', recipePath, error);
logger.error('failed to parse recipe json', recipePath, error);
}
}
@ -364,11 +365,11 @@
// No country file means Thailand
detectedCountry = 'THAI';
}
console.log('[CreateMenu] Detected country:', detectedCountry, '-> prefix:', detectedCountryCode);
logger.info('[CreateMenu] Detected country:', detectedCountry, '-> prefix:', detectedCountryCode);
} catch (error) {
// Error reading file means Thailand (default)
detectedCountry = 'THAI';
console.log('[CreateMenu] Country file not found, defaulting to THAI');
logger.info('[CreateMenu] Country file not found, defaulting to THAI');
} finally {
countryLoading = false;
}
@ -764,7 +765,7 @@
)
);
} catch (error) {
console.error('failed to persist staged menus to Android', error);
logger.error('failed to persist staged menus to Android', error);
addNotification('WARN:Failed to save draft menus to Android');
}
}
@ -798,7 +799,7 @@
}
return true;
} catch (error) {
console.error('failed to load staged menus from Android', error);
logger.error('failed to load staged menus from Android', error);
addNotification('WARN:Failed to load draft menus from Android');
return false;
}
@ -973,7 +974,7 @@
);
return;
}
console.log(
logger.info(
'[Create Menu] save all draft menus',
menus.map((menu) => menu.productCode)
);
@ -1171,7 +1172,7 @@
try {
boxid = (await adb.pull('/sdcard/coffeevending/.bid')) || undefined;
} catch (e) {
console.warn('Failed to get boxid from machine:', e);
logger.warn('Failed to get boxid from machine:', e);
}
}
requestListMenu('tha', boxid);

View file

@ -1,4 +1,5 @@
<script lang="ts">
<script lang="ts">import { logger } from '$lib/core/utils/logger';
import { auth } from '$lib/core/stores/auth';
import { addNotification } from '$lib/core/stores/noti';
import Button from '$lib/components/ui/button/button.svelte';
@ -171,7 +172,7 @@
} catch (error) {
files[index].status = 'error';
files[index].error = error instanceof Error ? error.message : 'Unknown error';
console.error(`Upload error for ${item.file.name}:`, error);
logger.error(`Upload error for ${item.file.name}:`, error);
}
}