feat: add ui block while brewing
- fix case value show invalid after come back from brewing finish (topping not save) - add update machine status Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
parent
4cb98f8672
commit
e25881d016
16 changed files with 371 additions and 17 deletions
|
|
@ -4,6 +4,9 @@
|
|||
import Label from '$lib/components/ui/label/label.svelte';
|
||||
import Input from '$lib/components/ui/input/input.svelte';
|
||||
import Button from '$lib/components/ui/button/button.svelte';
|
||||
import Spinner from '$lib/components/ui/spinner/spinner.svelte';
|
||||
import { Badge } from '$lib/components/ui/badge/index';
|
||||
import * as Item from '$lib/components/ui/item/index';
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||
import RecipelistTable from './recipelist-table.svelte';
|
||||
|
||||
|
|
@ -17,7 +20,7 @@
|
|||
materialFromServerQuery
|
||||
} from '$lib/core/stores/recipeStore';
|
||||
import { generateIcing } from '$lib/helpers/icingGen';
|
||||
import { machineInfoStore } from '$lib/core/stores/machineInfoStore';
|
||||
import { getMachineStatus, machineInfoStore } from '$lib/core/stores/machineInfoStore';
|
||||
import MachineInfo from '../machine-info.svelte';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { addNotification } from '$lib/core/stores/noti';
|
||||
|
|
@ -212,13 +215,13 @@
|
|||
</Tabs.List>
|
||||
{#if refPage === 'brew'}
|
||||
<div>
|
||||
<Button type="button" variant="default" onclick={() => resetAllPendingCmds()}
|
||||
>Force Reset Brewing</Button
|
||||
>
|
||||
<Button type="button" variant="default" onclick={() => saveRecipe()}>Save</Button>
|
||||
<Button type="button" variant="default" onclick={async () => sendTriggerBrewNow()}
|
||||
>Test Brew</Button
|
||||
>
|
||||
|
||||
{#if $machineInfoStore?.status == 'IDLE' || $machineInfoStore?.status == ''}
|
||||
<Button type="button" variant="default" onclick={async () => sendTriggerBrewNow()}
|
||||
>Test Brew</Button
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -244,12 +247,26 @@
|
|||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="details">
|
||||
<RecipelistTable
|
||||
data={recipeListMatState}
|
||||
{columns}
|
||||
onStateChange={checkChanges}
|
||||
{productCode}
|
||||
/>
|
||||
<!-- hide by machine state -->
|
||||
|
||||
{#if $machineInfoStore?.status == 'IDLE' || $machineInfoStore?.status == ''}
|
||||
<RecipelistTable
|
||||
data={recipeListMatState}
|
||||
{columns}
|
||||
onStateChange={checkChanges}
|
||||
{productCode}
|
||||
/>
|
||||
{:else}
|
||||
<Card.Root>
|
||||
<Card.Content>
|
||||
<div class="grid h-[60vh] w-full place-items-center rounded-md border">
|
||||
<div class="m-4 flex flex-row gap-2">
|
||||
<Spinner />Machine is working. Please wait for a moment.
|
||||
</div>
|
||||
</div>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
{/if}
|
||||
</Tabs.Content>
|
||||
</Tabs.Root>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
import { get } from 'svelte/store';
|
||||
|
||||
import * as Dialog from '$lib/components/ui/dialog/index';
|
||||
import Spinner from '$lib/components/ui/spinner/spinner.svelte';
|
||||
import { Badge } from '$lib/components/ui/badge/index';
|
||||
import RecipeDetail from './recipe-details/recipe-detail.svelte';
|
||||
import { MenuStatus, matchMenuStatus } from '$lib/core/types/menuStatus';
|
||||
|
||||
|
|
@ -23,6 +25,7 @@
|
|||
import { sendMessage } from '$lib/core/handlers/ws_messageSender';
|
||||
import { auth } from '$lib/core/stores/auth';
|
||||
import { departmentStore } from '$lib/core/stores/departments';
|
||||
import { getMachineStatus, machineInfoStore } from '$lib/core/stores/machineInfoStore';
|
||||
|
||||
const isDesktop = new MediaQuery('(min-width: 768px)');
|
||||
|
||||
|
|
@ -227,6 +230,9 @@
|
|||
|
||||
console.log('sending brewing payload', ready_to_send_brew);
|
||||
|
||||
// save topping
|
||||
latestRecipeToppingData.set(ready_to_send_brew[0]['ToppingSet']);
|
||||
|
||||
await sendToAndroid({
|
||||
type: 'brew',
|
||||
payload: {
|
||||
|
|
@ -285,7 +291,16 @@
|
|||
>
|
||||
<Dialog.Content class="sm:max-w-3/4">
|
||||
<Dialog.Header>
|
||||
<Dialog.Title>Edit Recipe {productCode}</Dialog.Title>
|
||||
<Dialog.Title
|
||||
>Edit Recipe {productCode}
|
||||
<Badge class="m-2">
|
||||
{#if $machineInfoStore?.status == 'IDLE' || $machineInfoStore?.status == ''}
|
||||
Ready
|
||||
{:else}
|
||||
<Spinner /> Brewing
|
||||
{/if}
|
||||
</Badge>
|
||||
</Dialog.Title>
|
||||
<Dialog.Description
|
||||
>Make changes to selected menu here. Click "save" when done or "test" for testing with
|
||||
connected machine
|
||||
|
|
|
|||
34
src/lib/components/ui/item/index.ts
Normal file
34
src/lib/components/ui/item/index.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import Root from "./item.svelte";
|
||||
import Group from "./item-group.svelte";
|
||||
import Separator from "./item-separator.svelte";
|
||||
import Header from "./item-header.svelte";
|
||||
import Footer from "./item-footer.svelte";
|
||||
import Content from "./item-content.svelte";
|
||||
import Title from "./item-title.svelte";
|
||||
import Description from "./item-description.svelte";
|
||||
import Actions from "./item-actions.svelte";
|
||||
import Media from "./item-media.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
Group,
|
||||
Separator,
|
||||
Header,
|
||||
Footer,
|
||||
Content,
|
||||
Title,
|
||||
Description,
|
||||
Actions,
|
||||
Media,
|
||||
//
|
||||
Root as Item,
|
||||
Group as ItemGroup,
|
||||
Separator as ItemSeparator,
|
||||
Header as ItemHeader,
|
||||
Footer as ItemFooter,
|
||||
Content as ItemContent,
|
||||
Title as ItemTitle,
|
||||
Description as ItemDescription,
|
||||
Actions as ItemActions,
|
||||
Media as ItemMedia,
|
||||
};
|
||||
20
src/lib/components/ui/item/item-actions.svelte
Normal file
20
src/lib/components/ui/item/item-actions.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="item-actions"
|
||||
class={cn("gap-2 flex items-center", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
23
src/lib/components/ui/item/item-content.svelte
Normal file
23
src/lib/components/ui/item/item-content.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="item-content"
|
||||
class={cn(
|
||||
"gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
23
src/lib/components/ui/item/item-description.svelte
Normal file
23
src/lib/components/ui/item/item-description.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
|
||||
</script>
|
||||
|
||||
<p
|
||||
bind:this={ref}
|
||||
data-slot="item-description"
|
||||
class={cn(
|
||||
"text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</p>
|
||||
20
src/lib/components/ui/item/item-footer.svelte
Normal file
20
src/lib/components/ui/item/item-footer.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="item-footer"
|
||||
class={cn("gap-2 flex basis-full items-center justify-between", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
21
src/lib/components/ui/item/item-group.svelte
Normal file
21
src/lib/components/ui/item/item-group.svelte
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
role="list"
|
||||
data-slot="item-group"
|
||||
class={cn("gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2 group/item-group flex w-full flex-col", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
20
src/lib/components/ui/item/item-header.svelte
Normal file
20
src/lib/components/ui/item/item-header.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="item-header"
|
||||
class={cn("gap-2 flex basis-full items-center justify-between", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
42
src/lib/components/ui/item/item-media.svelte
Normal file
42
src/lib/components/ui/item/item-media.svelte
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<script lang="ts" module>
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
|
||||
export const itemMediaVariants = tv({
|
||||
base: "gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start flex shrink-0 items-center justify-center [&_svg]:pointer-events-none",
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-transparent",
|
||||
icon: "[&_svg:not([class*='size-'])]:size-4",
|
||||
image: "size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
});
|
||||
|
||||
export type ItemMediaVariant = VariantProps<typeof itemMediaVariants>["variant"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
variant = "default",
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & { variant?: ItemMediaVariant } = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="item-media"
|
||||
data-variant={variant}
|
||||
class={cn(itemMediaVariants({ variant }), className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
19
src/lib/components/ui/item/item-separator.svelte
Normal file
19
src/lib/components/ui/item/item-separator.svelte
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { Separator } from "$lib/components/ui/separator/index.js";
|
||||
import { cn } from "$lib/utils.js";
|
||||
import type { ComponentProps } from "svelte";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
...restProps
|
||||
}: ComponentProps<typeof Separator> = $props();
|
||||
</script>
|
||||
|
||||
<Separator
|
||||
bind:ref
|
||||
data-slot="item-separator"
|
||||
orientation="horizontal"
|
||||
class={cn("my-2", className)}
|
||||
{...restProps}
|
||||
/>
|
||||
20
src/lib/components/ui/item/item-title.svelte
Normal file
20
src/lib/components/ui/item/item-title.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="item-title"
|
||||
class={cn("gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
61
src/lib/components/ui/item/item.svelte
Normal file
61
src/lib/components/ui/item/item.svelte
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<script lang="ts" module>
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
|
||||
export const itemVariants = tv({
|
||||
base: "[a]:hover:bg-muted rounded-lg border text-sm group/item focus-visible:border-ring focus-visible:ring-ring/50 flex w-full flex-wrap items-center transition-colors duration-100 outline-none focus-visible:ring-[3px] [a]:transition-colors",
|
||||
variants: {
|
||||
variant: {
|
||||
default: "border-transparent",
|
||||
outline: "border-border",
|
||||
muted: "bg-muted/50 border-transparent",
|
||||
},
|
||||
size: {
|
||||
default: "gap-2.5 px-3 py-2.5",
|
||||
sm: "gap-2.5 px-3 py-2.5",
|
||||
xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
});
|
||||
|
||||
export type ItemSize = VariantProps<typeof itemVariants>["size"];
|
||||
export type ItemVariant = VariantProps<typeof itemVariants>["variant"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
child,
|
||||
variant,
|
||||
size,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||
child?: Snippet<[{ props: Record<string, unknown> }]>;
|
||||
variant?: ItemVariant;
|
||||
size?: ItemSize;
|
||||
} = $props();
|
||||
|
||||
const mergedProps = $derived({
|
||||
class: cn(itemVariants({ variant, size }), className),
|
||||
"data-slot": "item",
|
||||
"data-variant": variant,
|
||||
"data-size": size,
|
||||
...restProps,
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if child}
|
||||
{@render child({ props: mergedProps })}
|
||||
{:else}
|
||||
<div bind:this={ref} {...mergedProps}>
|
||||
{@render mergedProps.children?.()}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -14,7 +14,9 @@
|
|||
bind:ref
|
||||
data-slot={dataSlot}
|
||||
class={cn(
|
||||
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:min-h-full data-[orientation=vertical]:w-px",
|
||||
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px",
|
||||
// this is different in shadcn/ui but self-stretch breaks things for us
|
||||
"data-[orientation=vertical]:h-full",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { updateMachineStatus } from '../stores/machineInfoStore';
|
||||
import { addNotification } from '../stores/noti';
|
||||
|
||||
type AdbPayload = { type: string; payload: any };
|
||||
|
|
@ -36,6 +37,7 @@ async function handleAdbPayload(raw_payload: string) {
|
|||
console.log('current state', curr, 'next state', next);
|
||||
|
||||
addNotification('INFO:Machine Status Updated, ' + next);
|
||||
updateMachineStatus(next);
|
||||
}
|
||||
break;
|
||||
case 'error':
|
||||
|
|
|
|||
|
|
@ -1,4 +1,19 @@
|
|||
import type { MachineInfo } from '$lib/models/machineInfo.model';
|
||||
import { writable } from 'svelte/store';
|
||||
import { get, writable } from 'svelte/store';
|
||||
|
||||
export const machineInfoStore = writable<MachineInfo | undefined>();
|
||||
const machineInfoStore = writable<MachineInfo | undefined>();
|
||||
|
||||
function updateMachineStatus(new_status: string) {
|
||||
let current = get(machineInfoStore);
|
||||
if (current) {
|
||||
current.status = new_status;
|
||||
|
||||
machineInfoStore.set(current);
|
||||
}
|
||||
}
|
||||
|
||||
function getMachineStatus() {
|
||||
return get(machineInfoStore)?.status;
|
||||
}
|
||||
|
||||
export { machineInfoStore, updateMachineStatus, getMachineStatus };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue