diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6d519d9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,41 @@ +# Build stage +FROM golang:1.24-alpine AS builder + +# Set working directory +WORKDIR /app + +# Copy go mod files first for better caching +COPY go.mod go.sum ./ + +# Download dependencies +RUN go mod download + +# Copy source code +COPY . . + +# Build the application +# Static binary without CGO +RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-w -s' -o meshi . + +# Runtime stage +FROM alpine:latest AS runtime + +# Create non-root user for security +RUN addgroup -g 1000 -S appgroup && \ + adduser -u 1000 -S appuser -G appgroup + +# Set working directory +WORKDIR /app + +# Copy binary from builder stage +COPY --from=builder /app/meshi . + +# Create data directory and set permissions +RUN mkdir -p /app/data && \ + chown -R appuser:appgroup /app + +# Switch to non-root user +USER appuser + +# Run the application +CMD ["./meshi"] \ No newline at end of file diff --git a/assets/css/input.css b/assets/css/input.css index ec85098..4f08a33 100644 --- a/assets/css/input.css +++ b/assets/css/input.css @@ -30,46 +30,77 @@ } :root { - --radius: 0.65rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); + --background: oklch(1 0 0); + --foreground: oklch(0.141 0.005 285.823); + --card: oklch(1 0 0); + --card-foreground: oklch(0.141 0.005 285.823); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.141 0.005 285.823); + --primary: oklch(54.6% 0.245 262.881); + --primary-foreground: oklch(0.97 0.014 254.604); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.967 0.001 286.375); + --muted-foreground: oklch(0.552 0.016 285.938); + --accent: oklch(0.967 0.001 286.375); + --accent-foreground: oklch(0.21 0.006 285.885); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.92 0.004 286.32); + --input: oklch(0.92 0.004 286.32); + --ring: oklch(0.623 0.214 259.815); + --radius: 0.65rem; + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.141 0.005 285.823); + --sidebar-primary: oklch(54.6% 0.245 262.881); + --sidebar-primary-foreground: oklch(0.97 0.014 254.604); + --sidebar-accent: oklch(0.94 0.001 286.375); + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); + --sidebar-border: oklch(0.92 0.004 286.32); + --sidebar-ring: oklch(0.623 0.214 259.815); + --selection: oklch(0.141 0.005 285.823); + --selection-foreground: oklch(1 0 0); } .dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); + --background: oklch(0.141 0.005 285.823); + --foreground: oklch(0.985 0 0); + --card: oklch(0.21 0.006 285.885); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.21 0.006 285.885); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(62.3% 0.214 259.815); + --primary-foreground: oklch(97% 0.014 254.604); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.274 0.006 286.033); + --muted-foreground: oklch(0.705 0.015 286.067); + --accent: oklch(0.274 0.006 286.033); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.488 0.243 264.376); + --radius: 0.65rem; + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.21 0.006 285.885); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(62.3% 0.214 259.815); + --sidebar-primary-foreground: oklch(97% 0.014 254.604); + --sidebar-accent: oklch(0.3 0.006 286.033); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.488 0.243 264.376); + --selection: oklch(0.92 0.004 286.32); + --selection-foreground: oklch(0.21 0.006 285.885); } @layer base { diff --git a/assets/css/output.css b/assets/css/output.css index 7c0a6e6..37f7ed6 100644 --- a/assets/css/output.css +++ b/assets/css/output.css @@ -176,6 +176,9 @@ .mt-4 { margin-top: calc(var(--spacing) * 4); } + .flex { + display: flex; + } .table { display: table; } @@ -297,45 +300,76 @@ } } :root { - --radius: 0.65rem; --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); + --foreground: oklch(0.141 0.005 285.823); --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); + --card-foreground: oklch(0.141 0.005 285.823); --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); + --popover-foreground: oklch(0.141 0.005 285.823); + --primary: oklch(54.6% 0.245 262.881); + --primary-foreground: oklch(0.97 0.014 254.604); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.967 0.001 286.375); + --muted-foreground: oklch(0.552 0.016 285.938); + --accent: oklch(0.967 0.001 286.375); + --accent-foreground: oklch(0.21 0.006 285.885); --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); + --border: oklch(0.92 0.004 286.32); + --input: oklch(0.92 0.004 286.32); + --ring: oklch(0.623 0.214 259.815); + --radius: 0.65rem; + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.141 0.005 285.823); + --sidebar-primary: oklch(54.6% 0.245 262.881); + --sidebar-primary-foreground: oklch(0.97 0.014 254.604); + --sidebar-accent: oklch(0.94 0.001 286.375); + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); + --sidebar-border: oklch(0.92 0.004 286.32); + --sidebar-ring: oklch(0.623 0.214 259.815); + --selection: oklch(0.141 0.005 285.823); + --selection-foreground: oklch(1 0 0); } .dark { - --background: oklch(0.145 0 0); + --background: oklch(0.141 0.005 285.823); --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); + --card: oklch(0.21 0.006 285.885); --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); + --popover: oklch(0.21 0.006 285.885); --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); + --primary: oklch(62.3% 0.214 259.815); + --primary-foreground: oklch(97% 0.014 254.604); + --secondary: oklch(0.274 0.006 286.033); --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); + --muted: oklch(0.274 0.006 286.033); + --muted-foreground: oklch(0.705 0.015 286.067); + --accent: oklch(0.274 0.006 286.033); --accent-foreground: oklch(0.985 0 0); --destructive: oklch(0.704 0.191 22.216); --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); + --ring: oklch(0.488 0.243 264.376); + --radius: 0.65rem; + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.21 0.006 285.885); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(62.3% 0.214 259.815); + --sidebar-primary-foreground: oklch(97% 0.014 254.604); + --sidebar-accent: oklch(0.3 0.006 286.033); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.488 0.243 264.376); + --selection: oklch(0.92 0.004 286.32); + --selection-foreground: oklch(0.21 0.006 285.885); } @layer base { * { diff --git a/csv/main.go b/csv/main.go index eac0e86..4ec2a32 100644 --- a/csv/main.go +++ b/csv/main.go @@ -16,7 +16,9 @@ func Load() (Plan, error) { return Plan{}, err } var menus [3][7]string - records, err := csv.NewReader(strings.NewReader(string(f))).ReadAll() + reader := csv.NewReader(strings.NewReader(string(f))) + reader.Comma = ';' + records, err := reader.ReadAll() for y := 0; y <= 2; y++ { for x := 0; x <= 6; x++ { menus[y][x] = records[y+1][x+1] diff --git a/plan.csv b/plan.csv index 8f4f7b6..4784ee2 100644 --- a/plan.csv +++ b/plan.csv @@ -1,4 +1,4 @@ -,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag -Frühstück,Test1,Test2,Test3,Test4,Test5,Test6,Test7 -Mittagessen,Test8,Test9,Test10,Test11,Test12,Test13,Test14 -Abendessen,Test15,Test16,Test17,Test18,Test19,Test20,Test21 \ No newline at end of file +;Montag;Dienstag;Mittwoch;Donnerstag;Freitag;Samstag;Sonntag +Frühstück;Test1;Test2;Test3;Test4;Test5;Test6;Test7 +Mittagessen;Test8;Test9;Test10;Test11;Test12;Test13;Test14 +Abendessen;Test15;Test16;Test17;Test18;Test19;Test20;Test21 diff --git a/ui/components/table/table.templ b/ui/components/table/table.templ index df7ba47..3a6be39 100644 --- a/ui/components/table/table.templ +++ b/ui/components/table/table.templ @@ -130,7 +130,7 @@ templ Row(props ...RowProps) { } class={ utils.TwMerge( - "border-b transition-colors hover:bg-muted/50", + "border-b transition-colors", utils.If(p.Selected, "data-[tui-table-state-selected]:bg-muted"), p.Class, ), diff --git a/ui/components/table/table_templ.go b/ui/components/table/table_templ.go index 87e52a7..2b9496c 100644 --- a/ui/components/table/table_templ.go +++ b/ui/components/table/table_templ.go @@ -453,7 +453,7 @@ func Row(props ...RowProps) templ.Component { p = props[0] } var templ_7745c5c3_Var18 = []any{utils.TwMerge( - "border-b transition-colors hover:bg-muted/50", + "border-b transition-colors", utils.If(p.Selected, "data-[tui-table-state-selected]:bg-muted"), p.Class, ), diff --git a/ui/pages/home_templ.go b/ui/pages/home_templ.go index dd5d98d..a733171 100644 --- a/ui/pages/home_templ.go +++ b/ui/pages/home_templ.go @@ -34,7 +34,7 @@ func Home(plan csv.Plan) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Menüplan") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Menüplan") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }