add recipe viewer

This commit is contained in:
Kenta420 2024-02-21 15:17:54 +07:00
parent 92b11f7b9d
commit f7f1535695
31 changed files with 1532 additions and 151 deletions

View file

@ -0,0 +1,198 @@
import { Input } from '@/components/ui/input'
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable'
import { Separator } from '@/components/ui/separator'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { TooltipProvider } from '@/components/ui/tooltip'
import { cn } from '@/lib/utils'
import { type Recipe01, type Recipes } from '@/models/recipe/schema'
import { memo, useMemo, useState } from 'react'
import AndroidSwitcher from './android-switcher'
import { Search, CupSoda, Wheat, Dessert, Cherry, WineOff } from 'lucide-react'
import Nav from './nav'
import RecipeList from './recipe-list'
import { isBefore, isToday } from 'date-fns'
import RecipeDisplay from './recipe-display'
interface RecipeMenuProps {
recipes: Recipes
recipe01: Recipe01[]
defaultSize?: number
isDevBranch: boolean
}
const RecipeMenu: React.FC<RecipeMenuProps> = memo(({ recipes, recipe01, defaultSize, isDevBranch }) => {
recipe01 = useMemo(() => {
return recipe01.sort((a, b) => (a.LastChange && b.LastChange && isBefore(a.LastChange, b.LastChange) ? 1 : -1))
}, [recipe01])
return (
<>
<ResizablePanel defaultSize={defaultSize} minSize={30}>
<Tabs defaultValue="all">
<div className="flex items-center px-4 py-2">
<h1 className="text-xl font-bold">
Recipe Version: {recipes.MachineSetting.configNumber} {isDevBranch ? '(Dev)' : ''}
</h1>
<TabsList className="ml-auto">
<TabsTrigger value="all" className="text-zinc-600 dark:text-zinc-200">
All Menu
</TabsTrigger>
<TabsTrigger value="today" className="text-zinc-600 dark:text-zinc-200">
Today
</TabsTrigger>
</TabsList>
</div>
<Separator />
<div className="bg-background/95 p-4 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<form>
<div className="relative">
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
<Input placeholder="Search" className="pl-8" />
</div>
</form>
</div>
<TabsContent value="all" className="m-0">
<RecipeList items={recipe01} />
</TabsContent>
<TabsContent value="today" className="m-0">
<RecipeList items={recipe01.filter(item => item.LastChange && isToday(item.LastChange))} />
</TabsContent>
</Tabs>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={defaultSize}>
<RecipeDisplay recipes={recipes} />
</ResizablePanel>
</>
)
})
interface RecipeEditorProps {
androids: {
label: string
deviceName: string
serial: string
icon: React.ReactNode
}[]
isDevBranch: boolean
recipes: Recipes
defaultLayout: number[] | undefined
defaultCollapsed?: boolean
navCollapsedSize: number
}
export const RecipeEditor: React.FC<RecipeEditorProps> = ({
androids,
recipes,
isDevBranch,
defaultLayout = [265, 440, 655],
defaultCollapsed = false,
navCollapsedSize
}) => {
const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed)
const [showListIndex, setShowListIndex] = useState(0)
const { recipesEnable, recipeDisable } = useMemo(() => {
return {
recipesEnable: recipes.Recipe01.filter(r => r.isUse),
recipeDisable: recipes.Recipe01.filter(r => !r.isUse)
}
}, [recipes])
return (
<TooltipProvider delayDuration={0}>
<ResizablePanelGroup
direction="horizontal"
onLayout={(sizes: number[]) => {
document.cookie = `react-resizable-panels:layout=${JSON.stringify(sizes)}`
}}
className="h-full max-h-[800px] items-stretch"
>
<ResizablePanel
defaultSize={defaultLayout[0]}
collapsedSize={navCollapsedSize}
collapsible={true}
minSize={15}
maxSize={20}
onCollapse={() => {
setIsCollapsed(true)
document.cookie = `react-resizable-panels:collapsed=${JSON.stringify(true)}`
}}
onExpand={() => {
setIsCollapsed(false)
document.cookie = `react-resizable-panels:collapsed=${JSON.stringify(false)}`
}}
className={cn(isCollapsed && 'min-w-[50px] transition-all duration-300 ease-in-out')}
>
<div className={cn('flex h-[52px] items-center justify-center', isCollapsed ? 'h-[52px]' : 'px-2')}>
<AndroidSwitcher isCollapsed={isCollapsed} androids={androids} />
</div>
<Separator />
<Nav
isCollapsed={isCollapsed}
showListIndex={showListIndex}
setShowListIndex={setShowListIndex}
links={[
{
index: 0,
title: 'Menu (Enabled)',
label: recipesEnable.length.toString(),
icon: CupSoda
},
{
index: 1,
title: 'Menu (Disabled)',
label: recipeDisable.length.toString(),
icon: WineOff
}
]}
/>
<Separator />
<Nav
isCollapsed={isCollapsed}
showListIndex={showListIndex}
setShowListIndex={setShowListIndex}
links={[
{
index: 2,
title: 'Materials',
label: recipes.MaterialSetting.length.toString(),
icon: Wheat
},
{
index: 3,
title: 'ToppingsGroups',
label: recipes.Topping.ToppingGroup.length.toString(),
icon: Dessert
},
{
index: 4,
title: 'ToppingsList',
label: recipes.Topping.ToppingList.length.toString(),
icon: Cherry
}
]}
/>
</ResizablePanel>
<ResizableHandle withHandle />
{showListIndex === 0 ? (
<RecipeMenu
recipes={recipes}
recipe01={recipesEnable}
defaultSize={defaultLayout[1]}
isDevBranch={isDevBranch}
/>
) : showListIndex === 1 ? (
<RecipeMenu
recipes={recipes}
recipe01={recipeDisable}
defaultSize={defaultLayout[1]}
isDevBranch={isDevBranch}
/>
) : null}
</ResizablePanelGroup>
</TooltipProvider>
)
}
export default RecipeEditor