change: remove loading while request recipe

progress: WIP editing flow

Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
pakintada@gmail.com 2026-03-24 17:52:53 +07:00
parent 3388eca2fe
commit e9192c8607
24 changed files with 538 additions and 81 deletions

View file

@ -112,7 +112,14 @@ export const columns: ColumnDef<RecipelistMaterial>[] = [
row_uid: row.original.id,
mat_id: row.original.material_id,
onEditValue: (changes: any) => {
recipeDataEvent.set({
event_type: 'edit_change_value_rpl',
payload: changes,
index: row.original.id
});
// get change parameters
row.toggleSelected(row.original.is_use);
},
onDetectMixOrder: () => {
// set next

View file

@ -20,13 +20,23 @@
import { onMount } from 'svelte';
import { addNotification } from '$lib/core/stores/noti';
import { get } from 'svelte/store';
import { ValueEvent } from './value_event';
import { actionReport, ValueEvent } from './value_event';
import ScrollArea from '../ui/scroll-area/scroll-area.svelte';
import { sendMessage } from '$lib/core/handlers/ws_messageSender';
import { auth } from '$lib/core/stores/auth';
import { departmentStore } from '$lib/core/stores/departments';
import { machineInfoStore } from '$lib/core/stores/machineInfoStore';
import type { setDefaultAutoSelectFamily } from 'node:net';
let { row_id }: { row_id: number } = $props();
let current_editing_data: any = $state();
let changed_data: any = $state();
let changed_data: any = $state({});
let sheetOpenState = $state(false);
let currentRef = $state('');
let warnUserNotSaveChange = $state(false);
// --------------------------------------------------
@ -76,7 +86,7 @@
// update value, do re-render
if (event.payload) {
current_editing_data = event.payload;
console.log(`GET requested data: ${JSON.stringify(current_editing_data)}`);
// console.log(`GET requested data: ${JSON.stringify(current_editing_data)}`);
// default topping
if (
@ -105,11 +115,15 @@
current_editing_data.water.yield > 0 || current_editing_data.water.cold > 0;
toggledOpenFeed =
current_editing_data.feed.pattern > 0 || current_editing_data.feed.parameter > 0;
sheetOpenState = true;
}
}
}
function requestDataFromDisplay() {
// pause show until have data
sheetOpenState = false;
console.log('sending request edit', row_id);
recipeDataEvent.set({
event_type: 'edit_mat_field',
@ -120,13 +134,12 @@
setTimeout(() => {
if (current_editing_data === undefined) {
addNotification('ERR:Unable to edit');
sheetOpenState = false;
}
}, 5000);
}
function onFieldValueChange(field_name: string[], new_value: any) {
console.log('change on', JSON.stringify(field_name), new_value);
// validate if field value changes
let curr_val;
for (let field of field_name) {
@ -147,43 +160,133 @@
if (has_changed) {
if (value_event_state === ValueEvent.NONE) {
value_event_state = ValueEvent.EDITED;
// save change
let single_key = '';
for (let field of field_name) {
single_key += field + '_';
}
single_key = single_key.slice(0, single_key.length - 1);
console.log('save to key', single_key);
changed_data[single_key] = new_value;
}
// save change
let single_key = '';
for (let field of field_name) {
single_key += field + '_';
}
single_key = single_key.slice(0, single_key.length - 1);
changed_data[single_key] = new_value;
} else {
// revert value in key
}
}
function saveEditingValue() {
console.log('saving value ...');
console.log('saving value ...', value_event_state);
if (value_event_state === ValueEvent.EDITED) {
let payload = {
source: current_editing_data,
change: changed_data
};
recipeDataEvent.set({
event_type: 'save_mat_field',
payload: current_editing_data,
payload,
index: row_id
});
value_event_state = ValueEvent.SAVED;
actionReport(
'change_mat_field',
{
index: row_id,
...payload
},
currentRef
);
sheetOpenState = false;
} else {
// set noti
addNotification(`WARN:Cannot save, please retry ...`);
}
}
function handleToppingGroupChange(v: any) {
console.log('change topping group', JSON.stringify(v));
console.log('change topping group');
selected_category_id = v.groupID;
// get default
selected_topping_list_id = v.idDefault ?? 0;
// set to edit state even if selected same group again
value_event_state = ValueEvent.EDITED;
if (current_editing_data['toppings']) {
let toppings_length = current_editing_data['toppings'].length;
if (!changed_data['toppings']) {
changed_data['toppings'] = new Array<any>(toppings_length);
// console.log('filling change topping', JSON.stringify(changed_data));
}
}
let idx = getToppingSlotIndex(current_editing_data['mat_id']);
// get old state topping idx
let current_selection = current_editing_data['toppings'][idx];
// let default_from_recipe = current_editing_data['toppings'][idx]['ListGroupID'][0];
// console.log(`Current TG: `, JSON.stringify(current_selection));
if (current_selection['groupID'] !== undefined || current_selection['groupID'] !== null) {
try {
changed_data['toppings'][idx] = current_selection;
changed_data['toppings'][idx]['groupID'] = `${selected_category_id}`;
changed_data['toppings'][idx]['defaultIDSelect'] = selected_topping_list_id;
changed_data['toppings'][idx]['ListGroupID'][0] = selected_topping_list_id;
} catch (topping_group_exception) {
console.error('Error on topping group select', topping_group_exception);
}
}
}
function handleToppingListChange(v: any) {
console.log('Topping list chose: ', JSON.stringify(v));
console.log('Topping list chose ');
selected_topping_list_id = v.id;
// set to edit state even if selected same group again
value_event_state = ValueEvent.EDITED;
let idx = getToppingSlotIndex(current_editing_data['mat_id']);
if (current_editing_data['toppings']) {
let toppings_length = current_editing_data['toppings'].length;
// case: topping not init
if (!changed_data['toppings']) {
changed_data['toppings'] = new Array<any>(toppings_length);
}
}
let current_selection = current_editing_data['toppings'][idx];
if (current_selection['groupID'] !== undefined || current_selection['groupID'] !== null) {
try {
changed_data['toppings'][idx] = current_selection;
// changed_data['toppings'][idx]['groupID'] = `${selected_category_id}`;
changed_data['toppings'][idx]['defaultIDSelect'] = selected_topping_list_id;
changed_data['toppings'][idx]['ListGroupID'][0] = selected_topping_list_id;
} catch (topping_list_exception) {
console.error('Error on topping group select', topping_list_exception);
}
}
}
function beforeClosing() {
if (value_event_state === ValueEvent.EDITED) {
if (warnUserNotSaveChange) {
// Discard all
warnUserNotSaveChange = false;
// sheetOpenState = false;
return true;
} else {
// show no save warning
warnUserNotSaveChange = true;
return false;
}
} else {
sheetOpenState = false;
return true;
}
}
// recipelist-value-editor.svelte?t=1773541064272:57 GET requested data: {"mat_id":1002,"mat_type":"bean","mat_name":"medium-roasts (1002)","params":{"esp-v2-press-value":"24"},"toppings":[{"ListGroupID":[1,0,0,0],"defaultIDSelect":1,"groupID":"1","isUse":true},{"ListGroupID":[6,0,0,0],"defaultIDSelect":31,"groupID":"6","isUse":true},{"ListGroupID":[7,0,0,0],"defaultIDSelect":33,"groupID":"7","isUse":true},{"ListGroupID":[0,0,0,0],"defaultIDSelect":0,"groupID":"0","isUse":false},{"ListGroupID":[0,0,0,0],"defaultIDSelect":0,"groupID":"0","isUse":false},{"ListGroupID":[0,0,0,0],"defaultIDSelect":0,"groupID":"0","isUse":false},{"ListGroupID":[530,0,0,0],"defaultIDSelect":532,"groupID":"530","isUse":true},{"ListGroupID":[500,0,0,0],"defaultIDSelect":502,"groupID":"500","isUse":true}],"current_topping_list":[],"has_mix_ord":false,"feed":{"pattern":0,"parameter":0},"water":{"cold":0,"yield":30},"powder":{"gram":7,"time":9},"syrup":{"gram":0,"time":0},"stir_time":120}
@ -192,6 +295,9 @@
// recipelist-value-editor.svelte?t=1773541064272:57 GET requested data: {"mat_id":9501,"mat_type":"cup","mat_name":"CUP paper (9501)","params":{},"toppings":[{"ListGroupID":[1,0,0,0],"defaultIDSelect":1,"groupID":"1","isUse":true},{"ListGroupID":[6,0,0,0],"defaultIDSelect":31,"groupID":"6","isUse":true},{"ListGroupID":[7,0,0,0],"defaultIDSelect":33,"groupID":"7","isUse":true},{"ListGroupID":[0,0,0,0],"defaultIDSelect":0,"groupID":"0","isUse":false},{"ListGroupID":[0,0,0,0],"defaultIDSelect":0,"groupID":"0","isUse":false},{"ListGroupID":[0,0,0,0],"defaultIDSelect":0,"groupID":"0","isUse":false},{"ListGroupID":[530,0,0,0],"defaultIDSelect":532,"groupID":"530","isUse":true},{"ListGroupID":[500,0,0,0],"defaultIDSelect":502,"groupID":"500","isUse":true}],"current_topping_list":[],"has_mix_ord":false,"feed":{"pattern":0,"parameter":0},"water":{"cold":0,"yield":0},"powder":{"gram":0,"time":0},"syrup":{"gram":0,"time":0},"stir_time":0}
onMount(() => {
sheetOpenState = false;
console.log('sheet open? ', sheetOpenState);
let refFrom = get(referenceFromPage);
categories = get(
refFrom === 'overview' ? toppingGroupFromServerQuery : toppingGroupFromMachineQuery
@ -200,6 +306,9 @@
refFrom === 'overview' ? toppingListFromServerQuery : toppingListFromMachineQuery
);
// save ref
currentRef = refFrom;
return recipeDataEvent.subscribe((event) => {
if (event !== null && event.index !== undefined && event.index === row_id) {
handleEvents(event);
@ -208,7 +317,16 @@
});
</script>
<Sheet.Root>
<Sheet.Root
bind:open={sheetOpenState}
onOpenChange={(next) => {
if (!next) {
beforeClosing();
} else {
sheetOpenState = true;
}
}}
>
<Sheet.Trigger>
<Button
variant="default"
@ -256,6 +374,15 @@
</Field.Set>
<ScrollArea class="h-[60vh] w-full" type="always">
{#if warnUserNotSaveChange}
<div class="flex flex-col items-center gap-2 text-center">
<h1 class="text-lg font-bold text-red-600">Unsaved changes may be lost.</h1>
<p class="text-balance text-red-700">
Click on "Discard Changes" to revert back values
</p>
</div>
{/if}
<!-- topping layout -->
<div
class={current_editing_data.mat_type === 'topping'
@ -487,10 +614,13 @@
</Field.Group>
</Field.Set>
</ScrollArea>
<!-- final -->
<Field.Field orientation="horizontal">
<Button type="button" onclick={() => saveEditingValue()}>Save</Button>
<Button variant="outline" type="button">Cancel</Button>
<Button variant="outline" type="button" onclick={() => beforeClosing()}
>{warnUserNotSaveChange ? 'Discard Changes' : 'Cancel'}</Button
>
</Field.Field>
</Field.Group>
</form>

View file

@ -170,7 +170,7 @@
if (currentToppings[getToppingSlot()]['ListGroupID'][0] === 0) {
return 'Empty';
}
if (!current_selected) {
if (current_selected === undefined || current_selected === null) {
return 'Unknown';
}
@ -237,11 +237,14 @@
},
index: row_uid
});
}
}
} else if (event.event_type === 'save_mat_field') {
console.log('receive saving process mat, do refresh...');
let change_values = event.payload.change;
function triggerEditChange(value: any) {
console.log('triggered on change editing', JSON.stringify(value));
// apply now
let keys = Object.keys(change_values);
console.log('change keys', JSON.stringify(keys));
}
}
onMount(() => {

View file

@ -1,6 +1,41 @@
import { get } from 'svelte/store';
import { auth } from '$lib/core/stores/auth';
import { departmentStore } from '$lib/core/stores/departments';
import { machineInfoStore } from '$lib/core/stores/machineInfoStore';
import { addNotification } from '$lib/core/stores/noti';
import { sendMessage } from '$lib/core/handlers/ws_messageSender';
enum ValueEvent {
NONE,
EDITED
EDITED,
SAVED
}
export { ValueEvent };
function actionReport(action_name: string, values: any, currentRef: string) {
let country = get(departmentStore) ?? 'unknown dep';
if (currentRef === 'brew') {
// from machine
let machine_info = get(machineInfoStore);
if (machine_info) {
let bid = machine_info.boxId ?? 'BOX_UNK';
let cc = machine_info.country;
country = `${bid}-${cc}`;
} else {
addNotification('WARN:Saving as unknown department, please check setting on machine');
}
}
sendMessage({
type: 'log_report',
payload: {
user: get(auth)?.email ?? 'unknown',
action: action_name,
country,
values
}
});
}
export { ValueEvent, actionReport };