diff --git a/app/components/cards/drink.page.tsx b/app/components/cards/drink.page.tsx
index 3d25f03..f609b2c 100644
--- a/app/components/cards/drink.page.tsx
+++ b/app/components/cards/drink.page.tsx
@@ -1,7 +1,8 @@
import { Manufacturer } from '@zenstackhq/runtime/models';
-import { Col, Container, Image, Row, Table } from 'react-bootstrap';
-import { ContainerWithSection, DrinkComposite, isDrinkWithContainersAndSection, isDrinkWithManufacturer, isDrinkWithStyle } from '~/models/types';
+import { Alert, Badge, Col, Container, Image, Row, Table } from 'react-bootstrap';
+import { ContainerWithSection, DrinkComposite, containerTypeToString, isBeer, isDrinkWithContainersAndSection, isDrinkWithManufacturer, isDrinkWithStyle } from '~/models/types';
+import { volume } from '~/utils/conversions';
interface Arguments {
drink: DrinkComposite
@@ -10,8 +11,10 @@ interface Arguments {
function DrinkPage(arg:Arguments) {
var borderColor = "#bbb";
+ var style = (<>>);
if(isDrinkWithStyle(arg.drink)){
borderColor = "#" + arg.drink.style.color;
+ style = ({arg.drink.style.name});
}
var manufacturer: Manufacturer | undefined = undefined;
@@ -19,40 +22,48 @@ function DrinkPage(arg:Arguments) {
manufacturer = arg.drink.manufacturer;
}
+ var glass = false;
+ var ibu = (<>>);
+ if(isBeer(arg.drink)){
+ glass = arg.drink.glass;
+ if(arg.drink.ibu)
+ ibu = ( 45 ? "warning" : "secondary"}>IBU: {arg.drink.ibu});
+ }
+
var containers : ContainerWithSection[] = [];
var totalinventory = 0;
+ var containerWithMultiplePortions = false;
if(isDrinkWithContainersAndSection(arg.drink)){
containers = arg.drink.containers;
containers.map((container) => {
totalinventory += container.inventory;
+
+ if((container.portions || 0) > 1){
+ containerWithMultiplePortions = true;
+ }
})
}
return (
+ {glass ? (
+
+ There is a glass available for this beer!
+
+ ): ""}
+
{arg.drink.name}
- ABV: {arg.drink.abv}% {arg.drink.gluten ? "" : " | Gluten-free"} {arg.drink.organic ? " | Organic" : ""}
+ 0 ? "warning" : "secondary"}>ABV: {arg.drink.abv}% {style} {ibu} {arg.drink.sugar ? "" : Sugar-free} {arg.drink.gluten ? "" : Gluten-free} {arg.drink.organic ? Organic : ""}
{arg.drink.description}
-
-
-
-
-
-
-
-
-
-
-
@@ -69,6 +80,7 @@ function DrinkPage(arg:Arguments) {
| Section |
Container |
+ Volume |
Amount |
@@ -76,13 +88,19 @@ function DrinkPage(arg:Arguments) {
{containers.map((container) => (
| {container.section.name} |
- {container.type} |
+ {containerTypeToString(container.type)} |
+ {volume(container.volume)} |
{container.inventory} |
))}
)}
+ {containerWithMultiplePortions ? (
+
+ This drink contains multiple portions! These should be scanned only when the container is empty!
+
+ ) : ""}
{ manufacturer ? (
diff --git a/app/components/filters/drink.filter.tsx b/app/components/filters/drink.filter.tsx
index ae9e68e..f5cce6b 100644
--- a/app/components/filters/drink.filter.tsx
+++ b/app/components/filters/drink.filter.tsx
@@ -90,7 +90,7 @@ function DrinkFilter(arg : Arguments) {
Drink
- { ["Gluten-free", "Organic"].map(key => (
+ { ["Sugar-free", "Gluten-free", "Organic"].map(key => (
[]}};
+ if(searchParams.has("sugar-free")){
+ whereBase.delegate_aux_drink.AND.push({NOT: {sugar: true}});
+ }
if(searchParams.has("gluten-free")){
whereBase.delegate_aux_drink.AND.push({NOT: {gluten: true}});
}
diff --git a/app/models/drinks.server.ts b/app/models/drinks.server.ts
index aeb82c3..182aa95 100644
--- a/app/models/drinks.server.ts
+++ b/app/models/drinks.server.ts
@@ -5,6 +5,9 @@ import { DrinkType, Manufacturer } from "@prisma/client";
export async function findIdFromSlug(slug:string | undefined) : Promise {
if(slug){
+ const id = Number(slug);
+ if(id) return id;
+
const drink = await db.drink.findUnique({where: {slug: slug}, select: {id: true}});
return drink?.id;
}
diff --git a/app/models/types.tsx b/app/models/types.tsx
index b13e1f5..154d72d 100644
--- a/app/models/types.tsx
+++ b/app/models/types.tsx
@@ -14,7 +14,7 @@ export type DrinkWithManufacturer = Drink & { manufacturer: Manufacturer}
export type BeerWithStyle = Beer & { style : BeerStyle }
export type WineWithStyle = Wine & { style : WineStyle }
-export type DrinkComposite = Drink | BeerWithStyle | WineWithStyle | Soda | Cocktail | DrinkWithManufacturer | DrinkWithContainers
+export type DrinkComposite = Drink | Beer | Wine | BeerWithStyle | WineWithStyle | Soda | Cocktail | DrinkWithManufacturer | DrinkWithContainers
export function isDrinkWithContainers(drink:DrinkComposite) : drink is DrinkWithContainers{
return ((drink as { containers: Container[]}).containers != undefined) || ((drink as { containers: ContainerWithSection[]}).containers != undefined);
@@ -43,10 +43,15 @@ export function isDrinkWithStyle(drink:DrinkComposite) : drink is WineWithStyle
return beerstyle || winestyle;
}
+export function isBeer(drink:DrinkComposite) : drink is Beer {
+ const beer = (drink as Beer).ibu != undefined;
+ return beer;
+}
+
export function containerTypeToString(type: ContainerType){
switch(type){
case "BeerBottle":
- return "Beer";
+ return "Beer bottle";
case "Can":
return "Can";
case "Carton":
@@ -54,6 +59,6 @@ export function containerTypeToString(type: ContainerType){
case "PlasticBottle":
return "PET";
case "WineBottle":
- return "Wine";
+ return "Wine bottle";
}
}
\ No newline at end of file
diff --git a/app/routes/admin/edit/beer.$id.tsx b/app/routes/admin/edit/beer.$id.tsx
new file mode 100644
index 0000000..562df32
--- /dev/null
+++ b/app/routes/admin/edit/beer.$id.tsx
@@ -0,0 +1,201 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, InputGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+
+ const slug = String(form.get("slug"));
+ const manufacturer = Number(form.get("manufacturer"));
+ const style = Number(form.get("style"));
+
+ const name = String(form.get("name"));
+ const description = String(form.get("description"));
+ var link : string | null = String(form.get("link")) || null;
+ if(link == "") link = null;
+
+ const abv = Number(form.get("abv"));
+ const ibu = Number(form.get("ibu"));
+
+ const glass = form.has("glass") ? true : false;
+
+ const sugar = form.has("sugar") ? true : false;
+ const gluten = form.has("gluten") ? true : false;
+ const lactose = form.has("lactose") ? true : false;
+ const organic = form.has("organic") ? true : false;
+
+ try{
+ await dbe.beer.update({ data: {
+ slug: slug,
+ name: name,
+ description: description,
+ link: link,
+ abv: abv,
+ ibu: ibu,
+ glass: glass,
+ sugar: sugar,
+ lactose: lactose,
+ gluten: gluten,
+ organic: organic,
+ manufacturer: {connect: {id: manufacturer}},
+ style: {connect: {id: style}}
+ }, where: {id: id}
+ });
+ return redirect("/inventory/beer/" + id);
+ }
+ catch(e){
+ console.log(e);
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const styles = await dbe.beerStyle.findMany({orderBy: {name: "asc"}});
+ const manufacturers = await dbe.manufacturer.findMany({orderBy: {name: "asc"}});
+
+ const beer = await dbe.beer.findUnique({where: {id: id}});
+
+ if(!beer) return redirect("/admin/edit/beer");
+
+ return json({styles, manufacturers, beer});
+}
+
+export default function EditBeerRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit beer ({loaderData.beer.id})
+
+ ID
+
+
+
+
+ Slug
+
+
+
+
+ Name
+
+
+
+
+ Description
+
+
+
+
+ Style
+
+ {loaderData.styles.map((style) => (
+
+ ))}
+
+
+
+
+ Manufacturer
+
+ {loaderData.manufacturers.map((manu) => (
+
+ ))}
+
+
+
+
+ ABV
+
+
+
+ %
+
+
+
+
+ IBU
+
+
+
+
+ Glass
+
+
+
+
+ Allergies
+
+
+
+
+
+
+
+ Link
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/beer.tsx b/app/routes/admin/edit/beer.tsx
new file mode 100644
index 0000000..130cecf
--- /dev/null
+++ b/app/routes/admin/edit/beer.tsx
@@ -0,0 +1,62 @@
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ //const beers = await dbe.beer.findMany({select: {id: true, name: true, _count: {select: {containers: true}}},orderBy: {name: "asc"}});
+ const beers = await dbe.beer.findMany({select: {id: true, slug: true, name: true, containers: true},orderBy: {name: "asc"}});
+ return json({beers});
+}
+
+export default function EditBeerRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit beer
+
+
+
+ {loaderData.beers.map((beer) => (
+
+ {beer.name} {beer.containers.length} Containers
+
+ { beer.containers.length <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/beerstyle.$id.tsx b/app/routes/admin/edit/beerstyle.$id.tsx
new file mode 100644
index 0000000..b3a62c3
--- /dev/null
+++ b/app/routes/admin/edit/beerstyle.$id.tsx
@@ -0,0 +1,75 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, Form, ListGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+ const name = String(form.get("name"));
+ const color = String(form.get("color")).replaceAll("#", "");
+
+ try{
+ await dbe.beerStyle.update({ data: {name: name, color: color}, where: {id: id} });
+ return redirect("/admin/edit/beerstyle");
+ }
+ catch(e){
+ console.log(e);
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const style = await dbe.beerStyle.findUnique({where: {id: id}});
+
+ if(!style) return redirect("/admin/edit/beerstyle");
+
+ return json({style});
+}
+
+export default function EditBeerStyleRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit Beer style ({loaderData.style.id})
+
+ ID
+
+
+
+
+ Style
+
+
+
+
+ Color
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/beerstyle.tsx b/app/routes/admin/edit/beerstyle.tsx
new file mode 100644
index 0000000..24658a0
--- /dev/null
+++ b/app/routes/admin/edit/beerstyle.tsx
@@ -0,0 +1,53 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { countBy } from "lodash";
+import { Container, Row, Col, Button, Form, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const beerstyles = await dbe.beerStyle.findMany({select: {id: true, name: true, color: true, _count: {select: {beers: true}}},orderBy: {name: "asc"}});
+ return json({beerstyles});
+}
+
+export default function EditBeerStyleRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit Beerstyle
+
+
+
+ {loaderData.beerstyles.map((style) => (
+
+ {style.name} {style._count.beers} Beers
+
+ { style._count.beers <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/cocktail.$id.tsx b/app/routes/admin/edit/cocktail.$id.tsx
new file mode 100644
index 0000000..636698d
--- /dev/null
+++ b/app/routes/admin/edit/cocktail.$id.tsx
@@ -0,0 +1,180 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, InputGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+
+ const slug = String(form.get("slug"));
+ const manufacturer = Number(form.get("manufacturer"));
+
+ const name = String(form.get("name"));
+ const description = String(form.get("description"));
+ var link : string | null = String(form.get("link")) || null;
+ if(link == "") link = null;
+
+ const abv = Number(form.get("abv"));
+
+ const mix = form.has("mix") ? true : false;
+
+ const sugar = form.has("sugar") ? true : false;
+ const gluten = form.has("gluten") ? true : false;
+ const lactose = form.has("lactose") ? true : false;
+ const organic = form.has("organic") ? true : false;
+
+ try{
+ await dbe.cocktail.update({ data: {
+ slug: slug,
+ name: name,
+ description: description,
+ link: link,
+ abv: abv,
+ mix: mix,
+ sugar: sugar,
+ lactose: lactose,
+ gluten: gluten,
+ organic: organic,
+ manufacturer: {connect: {id: manufacturer}}
+ }, where: {id: id}
+ });
+ return redirect("/inventory/cocktail/" + id);
+ }
+ catch(e){
+ console.log(e);
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const manufacturers = await dbe.manufacturer.findMany({orderBy: {name: "asc"}});
+
+ const cocktail = await dbe.cocktail.findUnique({where: {id: id}});
+
+ if(!cocktail) return redirect("/admin/edit/cocktail");
+
+ return json({manufacturers, cocktail});
+}
+
+export default function EditCocktailRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit cocktail ({loaderData.cocktail.id})
+
+ ID
+
+
+
+
+ Slug
+
+
+
+
+ Name
+
+
+
+
+ Description
+
+
+
+
+ Manufacturer
+
+ {loaderData.manufacturers.map((manu) => (
+
+ ))}
+
+
+
+
+ ABV
+
+
+
+ %
+
+
+
+
+ Cocktail specific
+
+
+
+
+ Allergies
+
+
+
+
+
+
+
+ Link
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/cocktail.tsx b/app/routes/admin/edit/cocktail.tsx
new file mode 100644
index 0000000..939b576
--- /dev/null
+++ b/app/routes/admin/edit/cocktail.tsx
@@ -0,0 +1,62 @@
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ //const cocktails = await dbe.cocktail.findMany({select: {id: true, name: true, _count: {select: {containers: true}}},orderBy: {name: "asc"}});
+ const cocktails = await dbe.cocktail.findMany({select: {id: true, slug: true, name: true, containers: true},orderBy: {name: "asc"}});
+ return json({cocktails});
+}
+
+export default function EditCocktailRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit cocktail
+
+
+
+ {loaderData.cocktails.map((cocktail) => (
+
+ {cocktail.name} {cocktail.containers.length} Containers
+
+ { cocktail.containers.length <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/container.$id.tsx b/app/routes/admin/edit/container.$id.tsx
new file mode 100644
index 0000000..cbb712a
--- /dev/null
+++ b/app/routes/admin/edit/container.$id.tsx
@@ -0,0 +1,157 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, Col, ListGroup, InputGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+import { ContainerType } from "@prisma/client";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+
+ var barcode : string | null = String(form.get("barcode")) || null;
+ if(barcode == "") barcode = null;
+
+ //const drink = Number(form.get("drink"));
+ const section = Number(form.get("section"));
+
+ const type = form.get("type") as ContainerType;
+ const volume = Number(form.get("volume"));
+ const portions = Number(form.get("portions"));
+ const price = Number(form.get("price"));
+ const inventory = Number(form.get("inventory"));
+
+ try{
+ const updatedContainer = await dbe.container.update({ data: {
+ barcode: barcode,
+ type: type,
+ volume: volume,
+ portions: portions,
+ price: price,
+ inventory: inventory,
+ //drink: {connect: {id: drink}},
+ section: {connect: {id: section}}
+ }, select: {drink: {select: {slug: true, type: true}}},
+ where: {id: id}
+ });
+ return redirect("/inventory/" + updatedContainer.drink.type.toLowerCase() + "/" + updatedContainer.drink.slug);
+ }
+ catch(e){
+
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const drinks = await dbe.drink.findMany({orderBy: {name: "asc"}});
+ const sections = await dbe.section.findMany({orderBy: {name: "asc"}});
+
+ const container = await dbe.container.findUnique({where: {id: id}});
+
+ if(!container) return redirect("/admin/edit/container");
+
+ return json({drinks, sections, container});
+}
+
+export default function EditContainerRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit Container ({loaderData.container.id})
+
+ ID
+
+
+
+
+ Barcode
+
+
+
+
+ Drink
+
+ {loaderData.drinks.map((drink) => (
+
+ ))}
+
+
+
+
+ Section
+
+ {loaderData.sections.map((section) => (
+
+ ))}
+
+
+
+
+ Container type
+
+
+
+
+
+
+
+
+
+
+ Volume
+
+
+
+ ml
+
+
+
+
+ Portions
+
+
+
+
+ Price
+
+
+ €
+
+
+
+
+
+ Inventory
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/container.tsx b/app/routes/admin/edit/container.tsx
new file mode 100644
index 0000000..389da2e
--- /dev/null
+++ b/app/routes/admin/edit/container.tsx
@@ -0,0 +1,55 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { countBy } from "lodash";
+import { Container, Row, Col, Button, Form, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+import { containerTypeToString } from "~/models/types";
+import { volume } from "~/utils/conversions";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const containers = await dbe.container.findMany({select: {id: true, drink: true, barcode: true, type: true, volume: true, inventory: true},orderBy: {drink: {name: "asc"}}});
+ return json({containers});
+}
+
+export default function EditContainerRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit container
+
+
+
+ {loaderData.containers.map((container) => (
+
+ {container.drink.name} - {containerTypeToString(container.type)} {volume(container.volume)} {container.inventory} inventory
+
+ { container.inventory <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/country.$code.tsx b/app/routes/admin/edit/country.$code.tsx
new file mode 100644
index 0000000..5177e97
--- /dev/null
+++ b/app/routes/admin/edit/country.$code.tsx
@@ -0,0 +1,69 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, Form, ListGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const code = params.code;
+
+ const form = await request.formData();
+ const name = String(form.get("name"));
+
+ try{
+ await dbe.country.update({ data: {name: name}, where: {code: code}});
+ return redirect("/admin/edit/country");
+ }
+ catch(e){
+
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const code = params.code;
+
+ const country = await dbe.country.findUnique({where: {code: code}});
+
+ if(!country) return redirect("/admin/edit/country");
+
+ return json({country});
+}
+
+export default function EditCountryRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit country ({loaderData.country.code})
+
+ Code
+
+
+
+
+ Country
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/country.tsx b/app/routes/admin/edit/country.tsx
new file mode 100644
index 0000000..8cda032
--- /dev/null
+++ b/app/routes/admin/edit/country.tsx
@@ -0,0 +1,53 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { countBy } from "lodash";
+import { Container, Row, Col, Button, Form, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const countries = await dbe.country.findMany({select: {name: true, code: true, _count: {select: {manufacturers: true}}},orderBy: {name: "asc"}});
+ return json({countries});
+}
+
+export default function EditCountryRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit country
+
+
+
+ {loaderData.countries.map((country) => (
+
+ {country.name} ({country.code}) {country._count.manufacturers} Manufactureres
+
+ { country._count.manufacturers <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/image/beer.$id.tsx b/app/routes/admin/edit/image/beer.$id.tsx
new file mode 100644
index 0000000..4fad076
--- /dev/null
+++ b/app/routes/admin/edit/image/beer.$id.tsx
@@ -0,0 +1,102 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, NodeOnDiskFile, json, redirect, unstable_composeUploadHandlers, unstable_createFileUploadHandler, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData } from "@remix-run/node";
+import { renameSync, rmSync } from "node:fs";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, Image } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const uploadHandler = unstable_composeUploadHandlers(
+ unstable_createFileUploadHandler({
+ file: ({ filename }) => filename.toLowerCase().replaceAll(" ", "_")
+ }),
+ // parse everything else into memory
+ unstable_createMemoryUploadHandler()
+ );
+ const parsedForm = await unstable_parseMultipartFormData(
+ request,
+ uploadHandler
+ );
+
+ const image = parsedForm.get("image") as NodeOnDiskFile;
+
+ const beer = await dbe.beer.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!beer) return redirect("/admin/edit/beer");
+
+ const newFilename = "/beers/" + beer.name.toLowerCase().replaceAll(" ", "_") + "." + image.name.split('.').pop();
+
+ try{
+ // Remove old image
+ if(beer.image) rmSync("public"+ beer.image, {force: true});
+
+ // Move the file to the beers folder with the slug as name
+ renameSync(image.getFilePath(), "public" + newFilename);
+
+ await dbe.beer.update({data: {image: newFilename}, where: {id: id}});
+
+ return redirect("/inventory/beer/" + id);
+ }
+ catch(e){
+ console.log(e);
+ rmSync(image.getFilePath(), {force: true});
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const beer = await dbe.beer.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!beer) return redirect("/admin/edit/beer");
+
+ return json({beer});
+}
+
+export default function EditBeerImageRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit beer image ({loaderData.beer.name})
+
+
+ Image
+
+
+
+
+
+
+
+ Current image
+ { loaderData.beer.image ? (
+ <>
+ {loaderData.beer.image}
+
+ >
+ ) : "No current image" }
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/image/cocktail.$id.tsx b/app/routes/admin/edit/image/cocktail.$id.tsx
new file mode 100644
index 0000000..608ce75
--- /dev/null
+++ b/app/routes/admin/edit/image/cocktail.$id.tsx
@@ -0,0 +1,102 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, NodeOnDiskFile, json, redirect, unstable_composeUploadHandlers, unstable_createFileUploadHandler, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData } from "@remix-run/node";
+import { renameSync, rmSync } from "node:fs";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, Image } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const uploadHandler = unstable_composeUploadHandlers(
+ unstable_createFileUploadHandler({
+ file: ({ filename }) => filename.toLowerCase().replaceAll(" ", "_")
+ }),
+ // parse everything else into memory
+ unstable_createMemoryUploadHandler()
+ );
+ const parsedForm = await unstable_parseMultipartFormData(
+ request,
+ uploadHandler
+ );
+
+ const image = parsedForm.get("image") as NodeOnDiskFile;
+
+ const cocktail = await dbe.cocktail.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!cocktail) return redirect("/admin/edit/cocktail");
+
+ const newFilename = "/cocktails/" + cocktail.name.toLowerCase().replaceAll(" ", "_") + "." + image.name.split('.').pop();
+
+ try{
+ // Remove old image
+ if(cocktail.image) rmSync("public"+ cocktail.image, {force: true});
+
+ // Move the file to the cocktails folder with the slug as name
+ renameSync(image.getFilePath(), "public" + newFilename);
+
+ await dbe.cocktail.update({data: {image: newFilename}, where: {id: id}});
+
+ return redirect("/inventory/cocktail/" + id);
+ }
+ catch(e){
+ console.log(e);
+ rmSync(image.getFilePath(), {force: true});
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const cocktail = await dbe.cocktail.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!cocktail) return redirect("/admin/edit/cocktail");
+
+ return json({cocktail});
+}
+
+export default function EditCocktailImageRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit cocktail image ({loaderData.cocktail.name})
+
+
+ Image
+
+
+
+
+
+
+
+ Current image
+ { loaderData.cocktail.image ? (
+ <>
+ {loaderData.cocktail.image}
+
+ >
+ ) : "No current image" }
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/image/manufacturer.$id.tsx b/app/routes/admin/edit/image/manufacturer.$id.tsx
new file mode 100644
index 0000000..4624e0b
--- /dev/null
+++ b/app/routes/admin/edit/image/manufacturer.$id.tsx
@@ -0,0 +1,102 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, NodeOnDiskFile, json, redirect, unstable_composeUploadHandlers, unstable_createFileUploadHandler, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData } from "@remix-run/node";
+import { renameSync, rmSync } from "node:fs";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, Image } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const uploadHandler = unstable_composeUploadHandlers(
+ unstable_createFileUploadHandler({
+ file: ({ filename }) => filename.toLowerCase().replaceAll(" ", "_")
+ }),
+ // parse everything else into memory
+ unstable_createMemoryUploadHandler()
+ );
+ const parsedForm = await unstable_parseMultipartFormData(
+ request,
+ uploadHandler
+ );
+
+ const image = parsedForm.get("image") as NodeOnDiskFile;
+
+ const manufacturer = await dbe.manufacturer.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!manufacturer) return redirect("/admin/edit/manufacturer");
+
+ const newFilename = "/manufacturers/" + manufacturer.name.toLowerCase().replaceAll(" ", "_") + "." + image.name.split('.').pop();
+
+ try{
+ // Remove old image
+ if(manufacturer.image) rmSync("public"+ manufacturer.image, {force: true});
+
+ // Move the file to the manufacturers folder with the slug as name
+ renameSync(image.getFilePath(), "public" + newFilename);
+
+ await dbe.manufacturer.update({data: {image: newFilename}, where: {id: id}});
+
+ return redirect("/inventory/manufacturer/" + id);
+ }
+ catch(e){
+ console.log(e);
+ rmSync(image.getFilePath(), {force: true});
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const manufacturer = await dbe.manufacturer.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!manufacturer) return redirect("/admin/edit/manufacturer");
+
+ return json({manufacturer});
+}
+
+export default function EditManufacturerImageRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit Manufacturer image ({loaderData.manufacturer.name})
+
+
+ Image
+
+
+
+
+
+
+
+ Current image
+ { loaderData.manufacturer.image ? (
+ <>
+ {loaderData.manufacturer.image}
+
+ >
+ ) : "No current image" }
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/image/soda.$id.tsx b/app/routes/admin/edit/image/soda.$id.tsx
new file mode 100644
index 0000000..e9ca425
--- /dev/null
+++ b/app/routes/admin/edit/image/soda.$id.tsx
@@ -0,0 +1,102 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, NodeOnDiskFile, json, redirect, unstable_composeUploadHandlers, unstable_createFileUploadHandler, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData } from "@remix-run/node";
+import { renameSync, rmSync } from "node:fs";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, Image } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const uploadHandler = unstable_composeUploadHandlers(
+ unstable_createFileUploadHandler({
+ file: ({ filename }) => filename.toLowerCase().replaceAll(" ", "_")
+ }),
+ // parse everything else into memory
+ unstable_createMemoryUploadHandler()
+ );
+ const parsedForm = await unstable_parseMultipartFormData(
+ request,
+ uploadHandler
+ );
+
+ const image = parsedForm.get("image") as NodeOnDiskFile;
+
+ const soda = await dbe.soda.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!soda) return redirect("/admin/edit/soda");
+
+ const newFilename = "/soda/" + soda.name.toLowerCase().replaceAll(" ", "_") + "." + image.name.split('.').pop();
+
+ try{
+ // Remove old image
+ if(soda.image) rmSync("public"+ soda.image, {force: true});
+
+ // Move the file to the sodas folder with the slug as name
+ renameSync(image.getFilePath(), "public" + newFilename);
+
+ await dbe.soda.update({data: {image: newFilename}, where: {id: id}});
+
+ return redirect("/inventory/soda/" + id);
+ }
+ catch(e){
+ console.log(e);
+ rmSync(image.getFilePath(), {force: true});
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const soda = await dbe.soda.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!soda) return redirect("/admin/edit/soda");
+
+ return json({soda});
+}
+
+export default function EditSodaImageRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit soda image ({loaderData.soda.name})
+
+
+ Image
+
+
+
+
+
+
+
+ Current image
+ { loaderData.soda.image ? (
+ <>
+ {loaderData.soda.image}
+
+ >
+ ) : "No current image" }
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/image/wine.$id.tsx b/app/routes/admin/edit/image/wine.$id.tsx
new file mode 100644
index 0000000..5a00830
--- /dev/null
+++ b/app/routes/admin/edit/image/wine.$id.tsx
@@ -0,0 +1,102 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, NodeOnDiskFile, json, redirect, unstable_composeUploadHandlers, unstable_createFileUploadHandler, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData } from "@remix-run/node";
+import { renameSync, rmSync } from "node:fs";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, Image } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const uploadHandler = unstable_composeUploadHandlers(
+ unstable_createFileUploadHandler({
+ file: ({ filename }) => filename.toLowerCase().replaceAll(" ", "_")
+ }),
+ // parse everything else into memory
+ unstable_createMemoryUploadHandler()
+ );
+ const parsedForm = await unstable_parseMultipartFormData(
+ request,
+ uploadHandler
+ );
+
+ const image = parsedForm.get("image") as NodeOnDiskFile;
+
+ const wine = await dbe.wine.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!wine) return redirect("/admin/edit/wine");
+
+ const newFilename = "/wine/" + wine.name.toLowerCase().replaceAll(" ", "_") + "." + image.name.split('.').pop();
+
+ try{
+ // Remove old image
+ if(wine.image) rmSync("public"+ wine.image, {force: true});
+
+ // Move the file to the wines folder with the slug as name
+ renameSync(image.getFilePath(), "public" + newFilename);
+
+ await dbe.wine.update({data: {image: newFilename}, where: {id: id}});
+
+ return redirect("/inventory/wine/" + id);
+ }
+ catch(e){
+ console.log(e);
+ rmSync(image.getFilePath(), {force: true});
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const wine = await dbe.wine.findUnique({select: {image: true, name: true}, where: {id: id}});
+
+ if(!wine) return redirect("/admin/edit/wine");
+
+ return json({wine});
+}
+
+export default function EditWineImageRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit wine image ({loaderData.wine.name})
+
+
+ Image
+
+
+
+
+
+
+
+ Current image
+ { loaderData.wine.image ? (
+ <>
+ {loaderData.wine.image}
+
+ >
+ ) : "No current image" }
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/manufacturer.$id.tsx b/app/routes/admin/edit/manufacturer.$id.tsx
new file mode 100644
index 0000000..ab9b96d
--- /dev/null
+++ b/app/routes/admin/edit/manufacturer.$id.tsx
@@ -0,0 +1,89 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+ const country = String(form.get("country"));
+ const name = String(form.get("name"));
+ const description = String(form.get("description"));
+
+ try{
+ await dbe.manufacturer.update({data: {name: name, description: description, country: {connect: {code: country}}}, where: {id: id} });
+ return redirect("/inventory/manufacturer/" + id);
+ }
+ catch(e){
+ console.log(e);
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const countries = await dbe.country.findMany({orderBy: {name: "asc"}});
+ const manufacturer = await dbe.manufacturer.findUnique({where: {id: id}});
+
+ if(!manufacturer) return redirect("/admin/edit/manufacturer");
+
+ return json({manufacturer, countries});
+}
+
+export default function NewManufacturerRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit Manufacturer ({loaderData.manufacturer.id})
+
+ ID
+
+
+
+
+ Country
+
+ {loaderData.countries.map((country) => (
+
+ ))}
+
+
+
+
+ Name
+
+
+
+
+ Description
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/manufacturer.tsx b/app/routes/admin/edit/manufacturer.tsx
new file mode 100644
index 0000000..fe04f68
--- /dev/null
+++ b/app/routes/admin/edit/manufacturer.tsx
@@ -0,0 +1,58 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { countBy } from "lodash";
+import { Container, Row, Col, Button, Form, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const manufacturers = await dbe.manufacturer.findMany({select: {id: true, name: true, _count: {select: {drinks: true}}},orderBy: {name: "asc"}});
+ return json({manufacturers});
+}
+
+export default function EditManufacturerRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit manufacturer
+
+
+
+ {loaderData.manufacturers.map((manufacturer) => (
+
+ {manufacturer.name} {manufacturer._count.drinks} Drinks
+
+ { manufacturer._count.drinks <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/beer.$id.tsx b/app/routes/admin/edit/remove/beer.$id.tsx
new file mode 100644
index 0000000..347c850
--- /dev/null
+++ b/app/routes/admin/edit/remove/beer.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.beer.delete({where: {id: id}});
+ return redirect("/admin/edit/beer");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/beerstyle.$id.tsx b/app/routes/admin/edit/remove/beerstyle.$id.tsx
new file mode 100644
index 0000000..e05bf92
--- /dev/null
+++ b/app/routes/admin/edit/remove/beerstyle.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.beerStyle.delete({where: {id: id}});
+ return redirect("/admin/edit/beerstyle");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/cocktail.$id.tsx b/app/routes/admin/edit/remove/cocktail.$id.tsx
new file mode 100644
index 0000000..aad51ed
--- /dev/null
+++ b/app/routes/admin/edit/remove/cocktail.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.cocktail.delete({where: {id: id}});
+ return redirect("/admin/edit/cocktail");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/container.$id.tsx b/app/routes/admin/edit/remove/container.$id.tsx
new file mode 100644
index 0000000..e42ed40
--- /dev/null
+++ b/app/routes/admin/edit/remove/container.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.container.delete({where: {id: id}});
+ return redirect("/admin/edit/container");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/country.$code.tsx b/app/routes/admin/edit/remove/country.$code.tsx
new file mode 100644
index 0000000..4b56db8
--- /dev/null
+++ b/app/routes/admin/edit/remove/country.$code.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const code = params.code;
+
+ await dbe.country.delete({where: {code: code}});
+ return redirect("/admin/edit/country");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/manufacturer.$id.tsx b/app/routes/admin/edit/remove/manufacturer.$id.tsx
new file mode 100644
index 0000000..b1aa652
--- /dev/null
+++ b/app/routes/admin/edit/remove/manufacturer.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.manufacturer.delete({where: {id: id}});
+ return redirect("/admin/edit/manufacturer");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/section.$id.tsx b/app/routes/admin/edit/remove/section.$id.tsx
new file mode 100644
index 0000000..2f55372
--- /dev/null
+++ b/app/routes/admin/edit/remove/section.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.section.delete({where: {id: id}});
+ return redirect("/admin/edit/section");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/soda.$id.tsx b/app/routes/admin/edit/remove/soda.$id.tsx
new file mode 100644
index 0000000..93f5ae5
--- /dev/null
+++ b/app/routes/admin/edit/remove/soda.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.soda.delete({where: {id: id}});
+ return redirect("/admin/edit/soda");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/wine.$id.tsx b/app/routes/admin/edit/remove/wine.$id.tsx
new file mode 100644
index 0000000..0c40529
--- /dev/null
+++ b/app/routes/admin/edit/remove/wine.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.wine.delete({where: {id: id}});
+ return redirect("/admin/edit/wine");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/remove/winestyle.$id.tsx b/app/routes/admin/edit/remove/winestyle.$id.tsx
new file mode 100644
index 0000000..e2a6f10
--- /dev/null
+++ b/app/routes/admin/edit/remove/winestyle.$id.tsx
@@ -0,0 +1,15 @@
+import { LoaderFunctionArgs, redirect } from "@remix-run/node";
+
+import { enhance } from "~/utils/db.server";
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ await dbe.wineStyle.delete({where: {id: id}});
+ return redirect("/admin/edit/winestyle");
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/route.tsx b/app/routes/admin/edit/route.tsx
new file mode 100644
index 0000000..94ceceb
--- /dev/null
+++ b/app/routes/admin/edit/route.tsx
@@ -0,0 +1,22 @@
+import { Link } from "@remix-run/react";
+import { ListGroup } from "react-bootstrap";
+
+export default function AdminRoute() {
+ return (
+
+
Edit or remove
+
+ country
+ section
+ beer style
+ wine style
+ manufacturer
+ beer
+ wine
+ soda
+ cocktail
+ container
+
+
+ );
+ }
\ No newline at end of file
diff --git a/app/routes/admin/edit/section.$id.tsx b/app/routes/admin/edit/section.$id.tsx
new file mode 100644
index 0000000..3390399
--- /dev/null
+++ b/app/routes/admin/edit/section.$id.tsx
@@ -0,0 +1,68 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, Form, ListGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+ const name = String(form.get("name"));
+
+ try{
+ await dbe.section.update({ data: {name: name}, where: {id: id} });
+ return redirect("/admin/edit/section");
+ }
+ catch(e){
+
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const section = await dbe.section.findUnique({where: {id: id}});
+
+ if(!section) return redirect("/admin/edit/section");
+
+ return json({section});
+}
+
+export default function EditSectionRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit Section ({loaderData.section.id})
+
+ ID
+
+
+
+ Section
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/section.tsx b/app/routes/admin/edit/section.tsx
new file mode 100644
index 0000000..0d60c0d
--- /dev/null
+++ b/app/routes/admin/edit/section.tsx
@@ -0,0 +1,53 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { countBy } from "lodash";
+import { Container, Row, Col, Button, Form, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const sections = await dbe.section.findMany({select: {name: true, id: true, _count: {select: {containers: true}}}, orderBy: {name: "asc"}});
+ return json({sections});
+}
+
+export default function EditSectionRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit section
+
+
+
+ {loaderData.sections.map((section) => (
+
+ {section.name} {section._count.containers} Containers
+
+ { section._count.containers <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/soda.$id.tsx b/app/routes/admin/edit/soda.$id.tsx
new file mode 100644
index 0000000..09c880b
--- /dev/null
+++ b/app/routes/admin/edit/soda.$id.tsx
@@ -0,0 +1,180 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, InputGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+
+ const slug = String(form.get("slug"));
+ const manufacturer = Number(form.get("manufacturer"));
+
+ const name = String(form.get("name"));
+ const description = String(form.get("description"));
+ var link : string | null = String(form.get("link")) || null;
+ if(link == "") link = null;
+
+ const abv = Number(form.get("abv"));
+
+ const carbonated = form.has("carbonated") ? true : false;
+
+ const sugar = form.has("sugar") ? true : false;
+ const gluten = form.has("gluten") ? true : false;
+ const lactose = form.has("lactose") ? true : false;
+ const organic = form.has("organic") ? true : false;
+
+ try{
+ await dbe.soda.update({ data: {
+ slug: slug,
+ name: name,
+ description: description,
+ link: link,
+ abv: abv,
+ carbonated: carbonated,
+ sugar: sugar,
+ lactose: lactose,
+ gluten: gluten,
+ organic: organic,
+ manufacturer: {connect: {id: manufacturer}}
+ }, where: { id: id}
+ });
+ return redirect("/inventory/soda/" + id);
+ }
+ catch(e){
+ console.log(e);
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const manufacturers = await dbe.manufacturer.findMany({orderBy: {name: "asc"}});
+
+ const soda = await dbe.soda.findUnique({where: {id: id}});
+
+ if(!soda) return redirect("/admin/edit/soda");
+
+ return json({manufacturers, soda});
+}
+
+export default function EditSodaRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit soda ({loaderData.soda.id})
+
+ ID
+
+
+
+
+ Slug
+
+
+
+
+ Name
+
+
+
+
+ Description
+
+
+
+
+ Manufacturer
+
+ {loaderData.manufacturers.map((manu) => (
+
+ ))}
+
+
+
+
+ ABV
+
+
+
+ %
+
+
+
+
+ Soda specific
+
+
+
+
+ Allergies
+
+
+
+
+
+
+
+ Link
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/soda.tsx b/app/routes/admin/edit/soda.tsx
new file mode 100644
index 0000000..962c24a
--- /dev/null
+++ b/app/routes/admin/edit/soda.tsx
@@ -0,0 +1,62 @@
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ //const sodas = await dbe.soda.findMany({select: {id: true, name: true, _count: {select: {containers: true}}},orderBy: {name: "asc"}});
+ const sodas = await dbe.soda.findMany({select: {id: true, slug: true, name: true, containers: true},orderBy: {name: "asc"}});
+ return json({sodas});
+}
+
+export default function EditSodaRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit soda
+
+
+
+ {loaderData.sodas.map((soda) => (
+
+ {soda.name} {soda.containers.length} Containers
+
+ { soda.containers.length <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/wine.$id.tsx b/app/routes/admin/edit/wine.$id.tsx
new file mode 100644
index 0000000..995b3e1
--- /dev/null
+++ b/app/routes/admin/edit/wine.$id.tsx
@@ -0,0 +1,227 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Button, Form, InputGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+
+ const slug = String(form.get("slug"));
+ const manufacturer = Number(form.get("manufacturer"));
+ const style = Number(form.get("style"));
+
+ const name = String(form.get("name"));
+ const description = String(form.get("description"));
+ var link : string | null = String(form.get("link")) || null;
+ if(link == "") link = null;
+
+ const abv = Number(form.get("abv"));
+
+ var heavy_score : number | null = Number(form.get("heavy_score"));
+ if(heavy_score < 0) heavy_score = null;
+ var tannine_score : number | null = Number(form.get("tannine_score"));
+ if(tannine_score < 0) tannine_score = null;
+ var dry_score : number | null = Number(form.get("dry_score"));
+ if(dry_score < 0) dry_score = null;
+ var fresh_score : number | null = Number(form.get("fresh_score"));
+ if(fresh_score < 0) fresh_score = null;
+
+ var notes : string | null = String(form.get("notes")) || null;
+ if(notes == "") notes = null;
+
+ const sugar = form.has("sugar") ? true : false;
+ const gluten = form.has("gluten") ? true : false;
+ const lactose = form.has("lactose") ? true : false;
+ const organic = form.has("organic") ? true : false;
+
+
+ try{
+ await dbe.wine.update({ data: {
+ slug: slug,
+ name: name,
+ description: description,
+ link: link,
+ abv: abv,
+ heavy_score: heavy_score,
+ tannine_score: tannine_score,
+ dry_score: dry_score,
+ fresh_score: fresh_score,
+ notes: notes,
+ sugar: sugar,
+ lactose: lactose,
+ gluten: gluten,
+ organic: organic,
+ manufacturer: {connect: {id: manufacturer}},
+ style: {connect: {id: style}}
+ }, where: {id: id}
+ });
+ return redirect("/inventory/wine/" + id);
+ }
+ catch(e){
+ console.log(e);
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const styles = await dbe.wineStyle.findMany({orderBy: {name: "asc"}});
+ const manufacturers = await dbe.manufacturer.findMany({orderBy: {name: "asc"}});
+
+ const wine = await dbe.wine.findUnique({where: {id: id}});
+
+ if(!wine) return redirect("/admin/edit/wine");
+
+ return json({styles, manufacturers, wine});
+}
+
+export default function EditWineRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit wine ({loaderData.wine.id})
+
+ ID
+
+
+
+
+ Slug
+
+
+
+
+ Name
+
+
+
+
+ Description
+
+
+
+
+ Style
+
+ {loaderData.styles.map((style) => (
+
+ ))}
+
+
+
+
+ Manufacturer
+
+ {loaderData.manufacturers.map((manu) => (
+
+ ))}
+
+
+
+
+ ABV
+
+
+
+ %
+
+
+
+
+ Heavy
+
+ Left = undefined, then light (0) - bold (5)
+
+
+
+ Tannine
+
+ Left = undefined, then smooth (0) - tannic (5)
+
+
+
+ Dryness
+
+ Left = undefined, then dry (0) - sweet (5)
+
+
+
+ Freshness
+
+ Left = undefined, then soft (0) - acidic (5)
+
+
+
+ Notes
+
+
+
+
+ Allergies
+
+
+
+
+
+
+
+ Link
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/wine.tsx b/app/routes/admin/edit/wine.tsx
new file mode 100644
index 0000000..6c7272a
--- /dev/null
+++ b/app/routes/admin/edit/wine.tsx
@@ -0,0 +1,62 @@
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ //const wines = await dbe.wine.findMany({select: {id: true, name: true, _count: {select: {containers: true}}},orderBy: {name: "asc"}});
+ const wines = await dbe.wine.findMany({select: {id: true, slug: true, name: true, containers: true}, orderBy: {name: "asc"}});
+ return json({wines});
+}
+
+export default function EditWineRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit wine
+
+
+
+ {loaderData.wines.map((wine) => (
+
+ {wine.name} {wine.containers.length} Containers
+
+ { wine.containers.length <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/winestyle.$id.tsx b/app/routes/admin/edit/winestyle.$id.tsx
new file mode 100644
index 0000000..f276d42
--- /dev/null
+++ b/app/routes/admin/edit/winestyle.$id.tsx
@@ -0,0 +1,75 @@
+import type { ActionFunctionArgs } from "@remix-run/node";
+import { LoaderFunctionArgs, json, redirect } from "@remix-run/node";
+import { useActionData, useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, Form, ListGroup } from "react-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+export const action = async ({
+ request,
+ params
+}: ActionFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const form = await request.formData();
+ const name = String(form.get("name"));
+ const color = String(form.get("color")).replaceAll("#", "");
+
+ try{
+ await dbe.wineStyle.update({ data: {name: name, color: color}, where: {id: id} });
+ return redirect("/admin/edit/winestyle");
+ }
+ catch(e){
+ console.log(e);
+ }
+
+ return null;
+};
+
+export const loader = async ({
+ request,
+ params
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const id = Number(params.id);
+
+ const style = await dbe.wineStyle.findUnique({where: {id: id}});
+
+ if(!style) return redirect("/admin/edit/winestyle");
+
+ return json({style});
+}
+
+export default function EditWineStyleRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+
+ Edit Wine style ({loaderData.style.id})
+
+ ID
+
+
+
+
+ Style
+
+
+
+
+ Color
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/winestyle.tsx b/app/routes/admin/edit/winestyle.tsx
new file mode 100644
index 0000000..c6ddbbe
--- /dev/null
+++ b/app/routes/admin/edit/winestyle.tsx
@@ -0,0 +1,51 @@
+import { LoaderFunctionArgs, json } from "@remix-run/node";
+import { useLoaderData } from "@remix-run/react";
+import { Container, Row, Col, Button, ListGroup, Badge } from "react-bootstrap";
+import { LinkContainer } from "react-router-bootstrap";
+
+import { enhance } from "~/utils/db.server";
+
+
+export const loader = async ({
+ request,
+} : LoaderFunctionArgs) => {
+ const { dbe } = await enhance(request);
+
+ const winestyles = await dbe.wineStyle.findMany({select: {id: true, name: true, color: true, _count: {select: {wines: true}}},orderBy: {name: "asc"}});
+ return json({winestyles});
+}
+
+export default function EditWineStyleRoute() {
+ var loaderData = useLoaderData();
+
+ return (
+
+ Edit Winestyle
+
+
+
+ {loaderData.winestyles.map((style) => (
+
+ {style.name} {style._count.wines} Wines
+
+ { style._count.wines <= 0 ? (
+
+
+
+ ) : "" }
+
+
+
+
+
+ ))}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/routes/admin/edit/checkout.tsx b/app/routes/admin/manage/checkout.tsx
similarity index 100%
rename from app/routes/admin/edit/checkout.tsx
rename to app/routes/admin/manage/checkout.tsx
diff --git a/app/routes/admin/edit/inventory.tsx b/app/routes/admin/manage/inventory.tsx
similarity index 100%
rename from app/routes/admin/edit/inventory.tsx
rename to app/routes/admin/manage/inventory.tsx
diff --git a/app/routes/admin/new/beer.tsx b/app/routes/admin/new/beer.tsx
index 525e8d0..9a7f828 100644
--- a/app/routes/admin/new/beer.tsx
+++ b/app/routes/admin/new/beer.tsx
@@ -35,17 +35,22 @@ export const action = async ({
const abv = Number(parsedForm.get("abv"));
const ibu = Number(parsedForm.get("ibu"));
+ const glass = parsedForm.has("glass") ? true : false;
+
+ const sugar = parsedForm.has("sugar") ? true : false;
const gluten = parsedForm.has("gluten") ? true : false;
const lactose = parsedForm.has("lactose") ? true : false;
const organic = parsedForm.has("organic") ? true : false;
const image = parsedForm.get("image") as NodeOnDiskFile;
- const newFilename = "/beers/" + slug + "." + image.name.split('.').pop();
+ var newFilename = null;
+ if(image.size > 0)
+ newFilename = "/beers/" + slug + "." + image.name.split('.').pop();
try{
// Move the file to the beers folder with the slug as name
- renameSync(image.getFilePath(), "public" + newFilename);
+ if(newFilename) renameSync(image.getFilePath(), "public" + newFilename);
const createdBeer = await dbe.beer.create({ data: {
slug: slug,
@@ -55,6 +60,8 @@ export const action = async ({
link: link,
abv: abv,
ibu: ibu,
+ glass: glass,
+ sugar: sugar,
lactose: lactose,
gluten: gluten,
organic: organic,
@@ -94,7 +101,7 @@ export default function NewBeerRoute() {
Slug
-
+
@@ -143,8 +150,24 @@ export default function NewBeerRoute() {
+
+ Glass
+
+
+
Allergies
+
Image
-
+
);
}
diff --git a/app/routes/scan/route.tsx b/app/routes/scan/route.tsx
index 0722805..d0c2e8d 100644
--- a/app/routes/scan/route.tsx
+++ b/app/routes/scan/route.tsx
@@ -86,7 +86,7 @@ export default function ScanRoute() {
- | Beer |
+ Drink |
When |
Amount left |
diff --git a/app/utils/conversions.ts b/app/utils/conversions.ts
new file mode 100644
index 0000000..646bcd7
--- /dev/null
+++ b/app/utils/conversions.ts
@@ -0,0 +1,8 @@
+export function volume(volume: number) : string {
+
+ if(volume < 1000){
+ return "" + volume + "ml";
+ }
+
+ return "" + (volume / 1000) + "l"
+}
\ No newline at end of file
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 188823b..fa8ab32 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -51,6 +51,7 @@ model Drink {
gluten Boolean
lactose Boolean
organic Boolean
+ sugar Boolean @default(true)
containers Container[]
delegate_aux_beer Beer?
delegate_aux_wine Wine?
@@ -67,6 +68,7 @@ model Beer {
style_id Int
style BeerStyle @relation(fields: [style_id], references: [id])
ibu Float?
+ glass Boolean @default(false)
delegate_aux_drink Drink @relation(fields: [id], references: [id], onDelete: Cascade, onUpdate: Cascade)
}
diff --git a/schema.zmodel b/schema.zmodel
index d0101e1..0b55147 100644
--- a/schema.zmodel
+++ b/schema.zmodel
@@ -50,6 +50,7 @@ model Drink {
gluten Boolean
lactose Boolean
organic Boolean
+ sugar Boolean @default(true)
containers Container[]
@@ -65,6 +66,8 @@ model Beer extends Drink {
ibu Float?
+ glass Boolean @default(false)
+
@@allow('read', true)
@@allow('all', auth().type == Admin)
}
diff --git a/vite.config.ts b/vite.config.ts
index a7a6465..35d3f41 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -9,12 +9,15 @@ export default defineConfig({
plugins: [remix({
routes(defineRoutes) {
return defineRoutes((route) => {
+
// Index
route("/", "routes/_index.tsx", { index: true });
+
// Resources
route("/resource/checkouts", "routes/resource/checkouts.tsx");
+
// Inventory
route("inventory", "routes/inventory/layout.tsx", () => {
route("", "routes/inventory/route.tsx", { index: true });
@@ -28,15 +31,18 @@ export default defineConfig({
});
+
// Scanner
route("scan", "routes/scan/layout.tsx", () => {
route("", "routes/scan/route.tsx", { index: true });
route("link/:barcode", "routes/scan/link.$barcode.tsx");
});
+
// Admin
route("admin", "routes/admin/layout.tsx", () => {
route("", "routes/admin/route.tsx", { index: true });
+
route("new", "routes/admin/new/route.tsx");
route("new/country", "routes/admin/new/country.tsx");
route("new/section", "routes/admin/new/section.tsx");
@@ -48,8 +54,56 @@ export default defineConfig({
route("new/cocktail", "routes/admin/new/cocktail.tsx");
route("new/container", "routes/admin/new/container.tsx");
route("new/manufacturer","routes/admin/new/manufacturer.tsx");
- route("edit/inventory", "routes/admin/edit/inventory.tsx");
- route("edit/checkout", "routes/admin/edit/checkout.tsx");
+
+ route("edit", "routes/admin/edit/route.tsx");
+
+ route("edit/country", "routes/admin/edit/country.tsx");
+ route("edit/country/:code", "routes/admin/edit/country.$code.tsx");
+ route("remove/country/:code", "routes/admin/edit/remove/country.$code.tsx");
+
+ route("edit/section", "routes/admin/edit/section.tsx");
+ route("edit/section/:id", "routes/admin/edit/section.$id.tsx");
+ route("remove/section/:id", "routes/admin/edit/remove/section.$id.tsx");
+
+ route("edit/beerstyle", "routes/admin/edit/beerstyle.tsx");
+ route("edit/beerstyle/:id", "routes/admin/edit/beerstyle.$id.tsx");
+ route("remove/beerstyle/:id", "routes/admin/edit/remove/beerstyle.$id.tsx");
+
+ route("edit/winestyle", "routes/admin/edit/winestyle.tsx");
+ route("edit/winestyle/:id", "routes/admin/edit/winestyle.$id.tsx");
+ route("remove/winestyle/:id", "routes/admin/edit/remove/winestyle.$id.tsx");
+
+ route("edit/manufacturer", "routes/admin/edit/manufacturer.tsx");
+ route("edit/manufacturer/:id", "routes/admin/edit/manufacturer.$id.tsx");
+ route("remove/manufacturer/:id", "routes/admin/edit/remove/manufacturer.$id.tsx");
+ route("edit/image/manufacturer/:id", "routes/admin/edit/image/manufacturer.$id.tsx");
+
+ route("edit/beer", "routes/admin/edit/beer.tsx");
+ route("edit/beer/:id", "routes/admin/edit/beer.$id.tsx");
+ route("remove/beer/:id", "routes/admin/edit/remove/beer.$id.tsx");
+ route("edit/image/beer/:id", "routes/admin/edit/image/beer.$id.tsx");
+
+ route("edit/wine", "routes/admin/edit/wine.tsx");
+ route("edit/wine/:id", "routes/admin/edit/wine.$id.tsx");
+ route("remove/wine/:id", "routes/admin/edit/remove/wine.$id.tsx");
+ route("edit/image/wine/:id", "routes/admin/edit/image/wine.$id.tsx");
+
+ route("edit/soda", "routes/admin/edit/soda.tsx");
+ route("edit/soda/:id", "routes/admin/edit/soda.$id.tsx");
+ route("remove/soda/:id", "routes/admin/edit/remove/soda.$id.tsx");
+ route("edit/image/soda/:id", "routes/admin/edit/image/soda.$id.tsx");
+
+ route("edit/cocktail", "routes/admin/edit/cocktail.tsx");
+ route("edit/cocktail/:id", "routes/admin/edit/cocktail.$id.tsx");
+ route("remove/cocktail/:id", "routes/admin/edit/remove/cocktail.$id.tsx");
+ route("edit/image/cocktail/:id", "routes/admin/edit/image/cocktail.$id.tsx");
+
+ route("edit/container", "routes/admin/edit/container.tsx");
+ route("edit/container/:id", "routes/admin/edit/container.$id.tsx");
+ route("remove/container/:id", "routes/admin/edit/remove/container.$id.tsx");
+
+ route("manage/inventory", "routes/admin/manage/inventory.tsx");
+ route("manage/checkout", "routes/admin/manage/checkout.tsx");
});
});
},