diff --git a/AjaxController.fs b/AjaxController.fs index f4a1731..e56e032 100644 --- a/AjaxController.fs +++ b/AjaxController.fs @@ -2,6 +2,7 @@ open DredgeFramework open DredgePos +open DredgePos.Types open Floorplan open Microsoft.AspNetCore.Http open Reservations @@ -57,6 +58,7 @@ let getOrderScreenData (id: int) = {| order_screen_pages = Entity.getAllInVenue sales_categories = Entity.getAllInVenue + print_groups = Entity.getAllInVenue |} |> ajaxSuccess |> json diff --git a/OrderScreen.module.fs b/OrderScreen.module.fs index 105ef1a..93a31d8 100644 --- a/OrderScreen.module.fs +++ b/OrderScreen.module.fs @@ -75,12 +75,13 @@ 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 printGroupPosButton (printGroup: print_group) = + PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """ let generateSalesCategoryOverrideButtons () = - Entity.getAllInVenue - |> Array.map categoryPosButton - |> Array.append ([|PosButton (language.getAndReplace "print_with" ["default"]) "categoryOverrideButton" ""|]) + Entity.getAllInVenue + |> Array.map printGroupPosButton + |> Array.append ([|PosButton (language.getAndReplace "print_with" ["default"]) "printGroupOverrideButton toggle default active" """data-value="0" """|]) |> String.concat "\n" diff --git a/Theme.module.fs b/Theme.module.fs index 3f18516..cc62dac 100644 --- a/Theme.module.fs +++ b/Theme.module.fs @@ -78,7 +78,7 @@ let ParseSimpleLanguageVariables (string:string) = let ParseLanguageVariablesWithReplacements (string: string) = Regex.Replace(string, "", - new MatchEvaluator( + MatchEvaluator( fun matchedVar -> let varName = matchedVar.Groups[1].ToString() let replacements = matchedVar.Groups[2].ToString() diff --git a/Types.fs b/Types.fs index daf1637..3f3ffaf 100644 --- a/Types.fs +++ b/Types.fs @@ -41,7 +41,7 @@ type sales_category = { id: int parent: int name: string - print_group: string + print_group: int venue_id: int } diff --git a/wwwroot/languages/english/main.json b/wwwroot/languages/english/main.json index cb21f77..65561fb 100644 --- a/wwwroot/languages/english/main.json +++ b/wwwroot/languages/english/main.json @@ -35,6 +35,7 @@ "functions_header":"Functions", "close_order_function":"Close Without Saving", "accumulate_function":"Accumulate Items", + "multiplier":"Enter a Number", "void":"Void", "pay_function":"Pay", "print_function":"Save & Print", diff --git a/wwwroot/scripts/ts/dredgepos.core.ts b/wwwroot/scripts/ts/dredgepos.core.ts index e456c6c..321614a 100644 --- a/wwwroot/scripts/ts/dredgepos.core.ts +++ b/wwwroot/scripts/ts/dredgepos.core.ts @@ -79,6 +79,7 @@ const setupCore = (languageVars: Record) => { Application.languageVars = languageVars const doc = $(document) doc.on('click', '#alertNo, #alertOk', hideAlerts) + doc.on('click', '.toggle', toggle) window.addEventListener('resize', resize) resize() @@ -194,6 +195,31 @@ Array.prototype.where = function(this: x[], property: string, value: any) { const money = (amount: number, fromCents=true) => currency(amount, {fromCents: fromCents}) const moneyFromString = (amount: string) => currency(amount) +const toggle = (e: JQuery.TriggeredEvent) => { + const button = $(e.target) + const toggleGroup = button.closest('.toggleGroup') + const input = toggleGroup.find('input.value') + const isActive = button.hasClass('active') + toggleGroup + .find('.toggle') + .removeClass('active') + + let value = !isActive + ? button.addClass('active').data('value') + : toggleGroup + .find('.toggle.default') + .addClass('active') + .data('value') + + input.val(value).trigger('change') +} + +const resetToggle = (input: JQuery) => { + input + .closest('.toggleGroup') + .find('.toggle.default') + .trigger('click') +} //Id generator. function* newestId(){ let id = 0 diff --git a/wwwroot/scripts/ts/dredgepos.orderScreen.ts b/wwwroot/scripts/ts/dredgepos.orderScreen.ts index d70176b..ab6f8bf 100644 --- a/wwwroot/scripts/ts/dredgepos.orderScreen.ts +++ b/wwwroot/scripts/ts/dredgepos.orderScreen.ts @@ -1,25 +1,31 @@ type OrderScreenData = { order_screen_pages: order_screen_page[] sales_categories: sales_category[] + print_groups: print_group[] } - type OrderScreen = { order_screen_pages: order_screen_page[] last_added_item: orderItem order_items: orderItem[] sales_categories: sales_category[] + print_groups: print_group[] order_item_id_generator: Generator selected_item_ids: number[] + qty_override: number + print_group_override: print_group } let OrderScreen : OrderScreen = { order_screen_pages: null, last_added_item: null, order_items: [], + print_groups: [], sales_categories: [], order_item_id_generator: newestId(), selected_item_ids: [], + qty_override: 1, + print_group_override: null } const loadPageGroup = (e: Event) => { @@ -42,6 +48,8 @@ const loadPageGroup = (e: Event) => { const setupOrderScreen = (data: OrderScreenData) => { OrderScreen.order_screen_pages = data.order_screen_pages OrderScreen.sales_categories = data.sales_categories + OrderScreen.print_groups = data.print_groups + updateOrderBoxTotals() let doc = $(document) doc.on('click', '.nextButton', goToNextPage) doc.on('click', '.prevButton', goToPrevPage) @@ -50,7 +58,9 @@ const setupOrderScreen = (data: OrderScreenData) => { doc.on('click', '.orderBoxTable tbody tr', itemRowClicked) doc.on('click', '.voidButton', voidButtonClicked) doc.on('dblclick', '.voidButton', voidLastItem) + doc.on('click', '.numpadButton', overrideQty) doc.on('click', '.accumulateButton', () => toggleMode('accumulate')) + doc.on('change', '[name=print_override]', printGroupOverride) turnOnMode('accumulate') @@ -64,7 +74,6 @@ const setupOrderScreen = (data: OrderScreenData) => { childList: true }); - } /** @@ -82,7 +91,12 @@ const addItemToOrderBox = (orderItem:orderItem) => { const orderBox = $('.orderBoxTable tbody') 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('tr') + .filterByData('item', orderItem.item) + .filterByData('print_group', orderItem.print_group) + .last() + //If accumulating, just increase the quantity of the existing row. if(existingRow.length > 0 && isInMode('accumulate')){ @@ -114,7 +128,6 @@ const addInstructionToOrderBox = (instruction: orderItem) => { 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()) @@ -128,14 +141,13 @@ const addInstructionToOrderBox = (instruction: orderItem) => { const addNewItem = (item: item, qty = 1) => { - const salesCategory = OrderScreen.sales_categories.where('id', item.item_category) - + const printGroup = OrderScreen.print_group_override ?? OrderScreen.print_groups.where('id', salesCategory.print_group) const orderItem : orderItem = { id: OrderScreen.order_item_id_generator.next().value, item: item, qty: qty, - sales_category: salesCategory, + print_group: printGroup, } switch(item.item_type){ @@ -202,13 +214,23 @@ const createOrderRow = (orderItem: orderItem) => { const price = money(orderItem.item.price1) row.data('order-item-id', orderItem.id) row.addClass(`${orderItem.item.item_type}Row`) + row .setColumnValue(lang('qty_header'), orderItem.qty) .setColumnValue(lang('item_header'), orderItem.item.item_name) .setColumnValue(lang('price_header'), price) - .setColumnValue(lang('total_price_header'), price) - .setColumnValue(lang('printgroup_header'), OrderScreen.sales_categories.where('id', orderItem.item.item_category)?.name) + .setColumnValue(lang('id_header'), orderItem.item.id) + .setColumnValue(lang('total_price_header'), price.multiply(orderItem.qty)) + .setColumnValue(lang('printgroup_header'), orderItem.print_group?.name) .data('order-item-id', orderItem.id) + .data('print_group', orderItem.print_group) + .data('item', orderItem.item) + + if(orderItem.item.item_type == 'instruction' && price.value <= 0){ + row + .find('.totalPriceCell') + .css('font-size', 0) + } return row } @@ -220,7 +242,10 @@ const itemButtonClicked = (e: JQuery.TriggeredEvent) => { if(item.item_type == 'instruction' && existingItemRows.length < 1) return - addNewItem(item) + const qty = OrderScreen.qty_override || 1 + OrderScreen.qty_override = 1 + + addNewItem(item, qty) } @@ -296,8 +321,11 @@ const voidLastItem = () => { const updateOrderBoxTotals = () => { const allRows = $('.orderBoxTable tbody tr') const selectedRows = $('.orderBoxTable tbody tr.selected') - $('.orderBoxTotal').text(getTotalOfRows(allRows)) - $('.orderBoxSelectedTotal').text(getTotalOfRows(selectedRows)) + const completeTotal = lang('totalPrice', getTotalOfRows(allRows)) + const selectedTotal = lang('selectedPrice', getTotalOfRows(selectedRows)) + + $('.orderBoxTotal').text(completeTotal) + $('.orderBoxSelectedTotal').text(selectedTotal) } const getTotalOfRows = (rows: JQuery) => { @@ -318,20 +346,45 @@ const calculateRowTotal = (row: JQuery) => { row.setColumnValue(lang('total_price_header'), price.multiply(qty)) } -const decrementQty = (row: JQuery) => { - const qty = getQty(row) - if(qty <= 1){ +const decrementQty = (row: JQuery, qty=1) => { + const existingQty = getQty(row) + + if(existingQty <= 1){ const childRows = row.nextUntil('.itemRow') deleteRow(row) deleteRow(childRows) return } - - row.setColumnValue(lang('qty_header'), qty - 1) + row.setColumnValue(lang('qty_header'), existingQty - qty) calculateRowTotal(row) } const scrollToElement = (element: JQuery) => element.get()[0].scrollIntoView() +const overrideQty = () => showVirtualNumpad(lang('multiplier'), 4, false, true, true, qtyOverridden) + + +const qtyOverridden = (qtyString: string) => OrderScreen.qty_override = Number(qtyString) + +const printGroupOverride = (e: JQuery.TriggeredEvent) => { + const input = $(e.target) + const printGroupId = Number(input.val()) + const orderBox = $('.orderBoxTable tbody') + const selectedRows = orderBox.find('tr.selected') + const newPrintGroup = OrderScreen.print_groups.where('id', printGroupId) + + if(selectedRows.length && newPrintGroup){ + selectedRows.each((index, row) => { + $(row).setColumnValue(lang('printgroup_header'), newPrintGroup.name) + $(row).data('print_group', newPrintGroup) + }) + + OrderScreen.print_group_override = null + resetToggle(input) + + } else { + OrderScreen.print_group_override = newPrintGroup + } +} $(() => ajax('/orderScreen/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null) ) \ No newline at end of file diff --git a/wwwroot/scripts/ts/types.ts b/wwwroot/scripts/ts/types.ts index aeaf028..f0a461c 100644 --- a/wwwroot/scripts/ts/types.ts +++ b/wwwroot/scripts/ts/types.ts @@ -10,11 +10,11 @@ interface order { interface orderItem { id: number, qty: number, - sales_category: sales_category + print_group: print_group item: item } -interface printGroup { +interface print_group { id: number, name: string, printer: number, diff --git a/wwwroot/styles/sass/dredgepos.core.sass b/wwwroot/styles/sass/dredgepos.core.sass index f91f57c..5ca8ff0 100644 --- a/wwwroot/styles/sass/dredgepos.core.sass +++ b/wwwroot/styles/sass/dredgepos.core.sass @@ -46,6 +46,7 @@ input[type=text], select, textarea bottom: 0 left: 0 right: 0 + z-index: 999 @mixin mobile @media screen and (max-width: 900px) diff --git a/wwwroot/styles/sass/dredgepos.orderScreen.sass b/wwwroot/styles/sass/dredgepos.orderScreen.sass index 2678e76..53d695c 100644 --- a/wwwroot/styles/sass/dredgepos.orderScreen.sass +++ b/wwwroot/styles/sass/dredgepos.orderScreen.sass @@ -51,8 +51,10 @@ > .orderBoxTotal align-items: flex-end - > small + font-size: 1.3em + > .orderBoxSelectedTotal align-items: flex-start + font-size: 0.9em #rightColumn @include flex-column @@ -68,24 +70,10 @@ flex-grow: 0 flex-shrink: 0 - .utilityButtons - @include flex-column-item - @include flex - flex-basis: 20% - - > * - @include flex-item - @include flex - flex-basis: 30% - - .logoutButton - flex-basis: 10% - - .functionButtons @include flex-column-item @include flex - flex-basis: 80% + flex-basis: 100% > * @include flex-item @@ -256,13 +244,13 @@ .itemCell text-align: center - width: 70% + width: 60% .qtyCell width: 10% .printGroupCell - width: 10% + width: 20% .totalPriceCell width: 10% @@ -271,9 +259,10 @@ text-align: left tr.instructionRow + td + font-weight: 100 td.itemCell padding-left: 2em - font-weight: 100 - .qtyCell, .totalPriceCell, .printGroupCell + .qtyCell, .printGroupCell font-size: 0 \ No newline at end of file diff --git a/wwwroot/themes/restaurant/orderScreen.tpl.htm b/wwwroot/themes/restaurant/orderScreen.tpl.htm index a452693..7dd837d 100644 --- a/wwwroot/themes/restaurant/orderScreen.tpl.htm +++ b/wwwroot/themes/restaurant/orderScreen.tpl.htm @@ -20,6 +20,7 @@ + @@ -33,30 +34,31 @@
- $0.00 - $0.00 + +
-
- - - - × -
-
- +
+ +
- + + + +
+
-
-
+
+ + +