diff --git a/OrderScreen.module.fs b/OrderScreen.module.fs index 3f02775..105ef1a 100644 --- a/OrderScreen.module.fs +++ b/OrderScreen.module.fs @@ -1,18 +1,12 @@ module OrderScreen -open System.Security.Cryptography.Xml -open System.Web open DredgeFramework open DredgePos +open DredgePos.Types open FSharp.Collections open Thoth.Json.Net open Types open Theme -let htmlAttributes (attributes: Map) = - " " + (attributes - |> Map.toArray - |> Array.map (fun (attribute, value) -> attribute+"='"+HttpUtility.HtmlEncode value + "'") - |> String.concat " ") let getAllPageGrids () = Entity.getAllInVenue |> Array.filter(fun pageGroup -> pageGroup.grid_id <> 0) @@ -81,6 +75,15 @@ let renderPageGroup (pageGroup: order_screen_page_group) (pageHTML: string) = ] loadTemplateWithVars "orderScreen/page_group" vars +let categoryPosButton (category: sales_category) = PosButton (language.getAndReplace "print_with" [category.name]) "categoryOverrideButton" "" + +let generateSalesCategoryOverrideButtons () = + Entity.getAllInVenue + |> Array.map categoryPosButton + |> Array.append ([|PosButton (language.getAndReplace "print_with" ["default"]) "categoryOverrideButton" ""|]) + |> String.concat "\n" + + let getPagesHTML (gridInfo: grid * order_screen_page_group) = let grid, pageGroup = gridInfo diff --git a/PageController.fs b/PageController.fs index a839b1b..3bfa88f 100644 --- a/PageController.fs +++ b/PageController.fs @@ -71,6 +71,7 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler = "orderNumber", orderNumber "coverSelectorButton", coverSelectorButton "covers", coverString + "salesCategoryOverrideButtons", OrderScreen.generateSalesCategoryOverrideButtons () ] let styles = ["dredgepos.orderScreen.css"] diff --git a/Theme.module.fs b/Theme.module.fs index 94b3eb5..3f18516 100644 --- a/Theme.module.fs +++ b/Theme.module.fs @@ -1,6 +1,6 @@ module Theme -open System +open System.Web open System.IO open System.Collections.Generic open System.Text.RegularExpressions @@ -137,4 +137,19 @@ let loadTemplateWithVarsAndScripts templateName vars scripts = let loadTemplateWithVarsAndStyles = loadTemplateWithVarsAndScripts let loadTemplateWithVarsScriptsAndStyles templateName vars scripts styles = - loadTemplateWithVarsArraysScriptsAndStyles templateName vars Map.empty> scripts styles \ No newline at end of file + loadTemplateWithVarsArraysScriptsAndStyles templateName vars Map.empty> scripts styles + + +let htmlAttributes (attributes: Map) = + " " + (attributes + |> Map.toArray + |> Array.map (fun (attribute, value) -> attribute+"='"+HttpUtility.HtmlEncode value + "'") + |> String.concat " ") + +let PosButton (text: string) (classes: string) (attributes: string) = + let vars = map [ + "text", text + "classes", classes + "attributes", attributes + ] + loadTemplateWithVars "components/posButton" vars \ No newline at end of file diff --git a/wwwroot/languages/english/main.json b/wwwroot/languages/english/main.json index 45f93c3..cb21f77 100644 --- a/wwwroot/languages/english/main.json +++ b/wwwroot/languages/english/main.json @@ -87,5 +87,7 @@ "partial_table":"Partial Table", "paying_table":"Paying Table [1]", "msgbox_amount_select":"Enter Amount", - "msgbox_qty_select":"How many would you like to select?" + "msgbox_qty_select":"How many would you like to select?", + + "void_mode": "Void Mode is ON." } \ No newline at end of file diff --git a/wwwroot/scripts/ts/dredgepos.floorplan.ts b/wwwroot/scripts/ts/dredgepos.floorplan.ts index 9e29c97..abbc912 100644 --- a/wwwroot/scripts/ts/dredgepos.floorplan.ts +++ b/wwwroot/scripts/ts/dredgepos.floorplan.ts @@ -221,6 +221,8 @@ const setupTableEvents = (tableGroup: Konva.Group) => { tableGroup.on('click', tableClicked) tableGroup.on('tap', tableClicked) + tableGroup.on('dbltap', tableDblClicked) + tableGroup.on('dblclick', tableDblClicked) tableGroup.on('dragend', tableGroupTransformed) tableShape.on('transformend', tableShapeTransformed) } @@ -438,7 +440,14 @@ const selectTable = (tableShape: Konva.Shape) => { const updateCoverText = (table:table) => $('.selectedTableCovers').text(lang('covers', table.default_covers.toString())) -const tableClicked = (event: Konva.KonvaEventObject) => { +const tableDblClicked = (event: Konva.KonvaEventObject) => { + let tableShape = getTableShapeFromGroup(event.currentTarget as Konva.Group) + const table = getTableDataFromShape(tableShape) + redirect(`/order/${table.table_number}`) +} + + + const tableClicked = (event: Konva.KonvaEventObject) => { let tableShape = getTableShapeFromGroup(event.currentTarget as Konva.Group) const table = getTableDataFromShape(tableShape) diff --git a/wwwroot/scripts/ts/dredgepos.orderScreen.ts b/wwwroot/scripts/ts/dredgepos.orderScreen.ts index e974f11..d34aa60 100644 --- a/wwwroot/scripts/ts/dredgepos.orderScreen.ts +++ b/wwwroot/scripts/ts/dredgepos.orderScreen.ts @@ -68,12 +68,58 @@ const navigatePage = (direction: number) => { const goToNextPage = () => navigatePage(1) const goToPrevPage = () => navigatePage(-1) -const addNewItem = (item: item, qty = 1) => { +const addItemToOrderBox = (orderItem:orderItem) => { const orderBox = $('.orderBoxTable tbody') - const lastRow = orderBox.find('tr').last() - const salesCategory = OrderScreen.sales_categories.where('id', item.item_category) + let selectedRows = orderBox.find('tr.selected') + let lastRow : JQuery = selectedRows.length ? selectedRows.first() : orderBox.find('tr').last() + const existingRow = orderBox.find(`.itemCell:contains("${orderItem.item.item_name}")`).closest('tr').last() - const existingRow = orderBox.find(`.itemCell:contains("${item.item_name}")`).closest('tr').last() + //If accumulating, just increase the quantity of the existing row. + if(existingRow.length > 0 && isInMode('accumulate')){ + incrementRowQty(existingRow, orderItem.qty) + scrollToElement(existingRow) + existingRow.pulse() + } else { + const newRow = createOrderRow(orderItem) + lastRow.length > 0 + ? lastRow.after(newRow) + : orderBox.append(newRow) + scrollToElement(newRow) + newRow.pulse() + } + + deselectRow(orderBox.find('tr')) +} + + +const addInstructionToOrderBox = (instruction: orderItem) => { + const orderBox = $('.orderBoxTable tbody') + let selectedRows = orderBox.find('tr.selected') + const newRow = createOrderRow(instruction) + + //If no items are added, then you can't add an instruction row. + if(!orderBox.find('tr.itemRow').length) return + + if(selectedRows.length > 0){ + selectedRows.each( (_, row) => { + const selectedRow = $(row) + const parentRow = getParentRow(selectedRow) + + if(parentRow.is(selectedRow) || !parentRow.hasClass('selected')) { + const newRow = createOrderRow(instruction) + getLastInstructionRow(selectedRow).after(newRow.pulse()) + } + }) + return + } + + orderBox.append(newRow.pulse()) +} + + +const addNewItem = (item: item, qty = 1) => { + + const salesCategory = OrderScreen.sales_categories.where('id', item.item_category) const orderItem : orderItem = { id: OrderScreen.order_item_id_generator.next().value, @@ -82,17 +128,37 @@ const addNewItem = (item: item, qty = 1) => { sales_category: salesCategory, } - if(existingRow.length > 0 && isInMode('accumulate') && orderItem.item.item_type != "instruction"){ - incrementRowQty(existingRow, qty) - existingRow.pulse() - } else { - const newRow = createOrderRow(orderItem) - lastRow.length > 0 - ? lastRow.after(newRow) - : orderBox.append(newRow) - newRow.pulse() + switch(item.item_type){ + case 'instruction': + addInstructionToOrderBox(orderItem) + break + case 'item': + default: + addItemToOrderBox(orderItem) + break } +} +const getLastInstructionRow = (row: JQuery) => { + let stopCounting = false + let finalRow = row + row.nextAll().each(function (index, activeRow){ + if(!stopCounting){ + if($(activeRow).hasClass('instructionRow')){ + finalRow = $(activeRow) + } else { + stopCounting = true + } + } + }) + + return $(finalRow) +} + +const getParentRow = (row: JQuery) => { + return row.hasClass('instructionRow') + ? row.prevAll('.itemRow').first() + : row } const incrementRowQty = (row: JQuery, qty: number) => { @@ -137,9 +203,6 @@ const createOrderRow = (orderItem: orderItem) => { return row } -const saveOrderItem = (orderItem: orderItem) => {} - - const itemButtonClicked = (e: JQuery.TriggeredEvent) => { const existingItemRows = $('.itemRow') const button = $(e.target).closest('.posButton') @@ -168,10 +231,6 @@ const itemRowClicked = (e: JQuery.TriggeredEvent) => { const selectRow = (row: JQuery) => { row.addClass('selected') - const id = row.data('order-item-id') - if(!OrderScreen.selected_item_ids.includes(id)) - OrderScreen.selected_item_ids.push(id) - const instructionRows = row.nextUntil('.itemRow') if(row.hasClass('itemRow') && instructionRows.length){ @@ -184,7 +243,6 @@ const selectRow = (row: JQuery) => { const deselectRow = (row: JQuery) => { row.removeClass('selected') const instructionRows = row.nextUntil('.itemRow') - OrderScreen.selected_item_ids = OrderScreen.selected_item_ids.filter(id => id != row.data('order-item-id')) if(row.hasClass('itemRow') && instructionRows.length){ deselectRow(instructionRows) @@ -194,9 +252,8 @@ const deselectRow = (row: JQuery) => { const deleteRow = (row: JQuery) => row.find('*:not(.hidden)').slideUp('fast', () => row.remove()) const voidInstructionRow = (row: JQuery) => { - const parentRow = row.prevAll('.itemRow').first() - - deleteRow(row) + if(!row.prevAll('.itemRow').first().hasClass('selected')) + deleteRow(row) } const voidItemRow = (row : JQuery) => decrementQty(row) @@ -237,7 +294,9 @@ const calculateRowTotal = (row: JQuery) => { const decrementQty = (row: JQuery) => { const qty = getQty(row) if(qty <= 1){ + const childRows = row.nextUntil('.itemRow') deleteRow(row) + deleteRow(childRows) return } @@ -245,6 +304,7 @@ const decrementQty = (row: JQuery) => { calculateRowTotal(row) } -const getOrderItemRow = (orderItem: orderItem) => $('tr').filterByData('order-item-id', orderItem.id) +const scrollToElement = (element: JQuery) => element.get()[0].scrollIntoView() + $(() => ajax('/orderScreen/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null) ) \ No newline at end of file diff --git a/wwwroot/styles/sass/dredgepos.orderScreen.sass b/wwwroot/styles/sass/dredgepos.orderScreen.sass index f3a3c7a..2678e76 100644 --- a/wwwroot/styles/sass/dredgepos.orderScreen.sass +++ b/wwwroot/styles/sass/dredgepos.orderScreen.sass @@ -29,11 +29,30 @@ overflow-y: auto .orderBoxInfo + @include flex flex-basis: 5% background-color: white + .voidModeWarning + @include flex + @include flex-item + color: red + font-weight: bold + .orderBoxFooter flex-basis: 10% + @include flex-column + + > * + @include flex + @include flex-column-item + justify-content: flex-end + padding: 0 0.7em + + > .orderBoxTotal + align-items: flex-end + > small + align-items: flex-start #rightColumn @include flex-column @@ -239,6 +258,15 @@ text-align: center width: 70% + .qtyCell + width: 10% + + .printGroupCell + width: 10% + + .totalPriceCell + width: 10% + td.itemCell text-align: left diff --git a/wwwroot/themes/restaurant/components/posButton.tpl.htm b/wwwroot/themes/restaurant/components/posButton.tpl.htm new file mode 100644 index 0000000..6cec82e --- /dev/null +++ b/wwwroot/themes/restaurant/components/posButton.tpl.htm @@ -0,0 +1,3 @@ +> + + \ No newline at end of file diff --git a/wwwroot/themes/restaurant/orderScreen.tpl.htm b/wwwroot/themes/restaurant/orderScreen.tpl.htm index e4f7c3b..a452693 100644 --- a/wwwroot/themes/restaurant/orderScreen.tpl.htm +++ b/wwwroot/themes/restaurant/orderScreen.tpl.htm @@ -29,9 +29,12 @@ -
+
+ +
- + $0.00 + $0.00
@@ -44,12 +47,7 @@
- - - - - - +