OrderScreen complete

This commit is contained in:
2022-01-23 18:16:18 +10:00
parent 75c129c5d4
commit 445cbbabe5
21 changed files with 609 additions and 281 deletions

View File

@@ -42,24 +42,25 @@ let unmergeTable tableNumber =
let getFloorplanData (id: int) = let getFloorplanData (id: int) =
let tableList = Entity.getAllInVenue<floorplan_table> let tableList = Entity.GetAllInVenue<floorplan_table>
let reservationList = getReservationList tableList let reservationList = getReservationList tableList
{| {|
tables = tableList tables = tableList
decorations = Entity.getAllInVenue<floorplan_decoration> decorations = Entity.GetAllInVenue<floorplan_decoration>
activeTableNumbers = Floorplan.getActiveTables (getCurrentVenue()) activeTableNumbers = Floorplan.getActiveTables (getCurrentVenue())
rooms = Entity.getAllInVenue<floorplan_room> rooms = Entity.GetAllInVenue<floorplan_room>
reservations = reservationList reservations = reservationList
|} |}
|> ajaxSuccess |> ajaxSuccess
|> json |> json
let getOrderScreenData (id: int) = let getOrderScreenData (tableNumber: int) =
{| {|
order_screen_pages = Entity.getAllInVenue<order_screen_page_group> order_screen_pages = Entity.GetAllInVenue<order_screen_page_group>
sales_categories = Entity.getAllInVenue<sales_category> sales_categories = Entity.GetAllInVenue<sales_category>
print_groups = Entity.getAllInVenue<print_group> print_groups = Entity.GetAllInVenue<print_group>
custom_item = Entity.getAllByColumn<item> "item_code" "OPEN000" |> first custom_item = Entity.GetAllByColumn<item> "item_code" "OPEN000" |> first
table = getTable tableNumber
|} |}
|> ajaxSuccess |> ajaxSuccess
|> json |> json
@@ -73,21 +74,18 @@ let getKeyboardLayout (language: string) =
] |> json ] |> json
let transformTable (table: floorplan_table) = let transformTable (table: floorplan_table) =
Entity.updateInDatabase table Entity.Update table
|> ajaxSuccess |> ajaxSuccess
|> json |> json
let createTable (tableData: floorplan_table) = let createTable (tableData: floorplan_table) =
if tableExists tableData.table_number = "False" then
let result = ajaxSuccess (addNewTable tableData)
if tableExists tableData.table_number = "False" then else ajaxFail (tableExists tableData.table_number)
ajaxSuccess (addNewTable tableData) |> json
else ajaxFail (tableExists tableData.table_number)
result |> json
let deleteTable (table: floorplan_table) = let deleteTable (table: floorplan_table) =
Entity.deleteById<floorplan_table> table.id Entity.DeleteById<floorplan_table> table.id
|> ignore |> ignore
table |> ajaxSuccess |> json table |> ajaxSuccess |> json
@@ -113,30 +111,30 @@ let AddDecoration (data: floorplan_decoration) =
venue_id = data.venue_id venue_id = data.venue_id
} }
Entity.addToDatabase decoration Entity.Create decoration
|> ajaxSuccess |> ajaxSuccess
|> json |> json
let UpdateDecoration (data: floorplan_decoration) = let UpdateDecoration (data: floorplan_decoration) =
Entity.updateInDatabase data Entity.Update data
|> ignore |> ignore
ajaxSuccess "true" |> json ajaxSuccess "true" |> json
let DeleteDecoration (decorationToDelete: floorplan_decoration) = let DeleteDecoration (decorationToDelete: floorplan_decoration) =
Entity.deleteById<floorplan_decoration> decorationToDelete.id Entity.DeleteById<floorplan_decoration> decorationToDelete.id
|> ajaxSuccess |> ajaxSuccess
|> json |> json
let newEmptyReservation (reservation: reservation) = let newEmptyReservation (reservation: reservation) =
let newReservation = {reservation with let newReservation = {reservation with
reservation_created_at = CurrentTime() created_at = CurrentTime()
reservation_time = CurrentTime() time = CurrentTime()
} }
if reservation.reservation_table_id > 0 then if reservation.floorplan_table_id > 0 then
let table = {(getTableById reservation.reservation_table_id) with let table = {(getTableById reservation.floorplan_table_id) with
status = 2 status = 2
default_covers = reservation.reservation_covers} default_covers = reservation.covers}
updateTablePosition table |> ignore updateTablePosition table |> ignore
let createdReservation = Floorplan.createEmptyReservation newReservation let createdReservation = Floorplan.createEmptyReservation newReservation
@@ -149,3 +147,10 @@ let unreserveTable (table: floorplan_table) =
updateTablePosition newTable |> ignore updateTablePosition newTable |> ignore
DeleteReservation newTable.id DeleteReservation newTable.id
newTable |> ajaxSuccess |> json newTable |> ajaxSuccess |> json
let loadGrid (gridId: int) =
let grid = Entity.GetById<grid> gridId
let gridHtml = OrderScreen.loadGrid gridId
if gridHtml = "Error" then ajaxFail gridHtml
else ajaxSuccess {|grid=grid;gridHtml=gridHtml|}
|> json

View File

@@ -8,7 +8,7 @@ open Dapper.FSharp
open DredgePos open DredgePos
open Types open Types
let decorationsInRoom (roomId: int) = Entity.getAllByColumn "decoration_room" roomId let decorationsInRoom (roomId: int) = Entity.GetAllByColumn "decoration_room" roomId
let getImageName (image: string, path: string) = let getImageName (image: string, path: string) =
let imageName = let imageName =

View File

@@ -61,6 +61,7 @@
<PackageReference Include="SQLProvider" Version="1.2.1" /> <PackageReference Include="SQLProvider" Version="1.2.1" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0-preview.5.21301.5" /> <PackageReference Include="System.Drawing.Common" Version="6.0.0-preview.5.21301.5" />
<PackageReference Include="Thoth.Json.Net" Version="5.0.0" /> <PackageReference Include="Thoth.Json.Net" Version="5.0.0" />
<PackageReference Update="FSharp.Core" Version="6.0.2-beta.21631.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,6 +1,7 @@
module Floorplan module Floorplan
open DredgePos open DredgePos
open DredgePos.Types
open Org.BouncyCastle.Asn1.X509 open Org.BouncyCastle.Asn1.X509
open Reservations open Reservations
@@ -116,16 +117,16 @@ let getRoom (roomId: int) =
where (eq "id" roomId) where (eq "id" roomId)
} |> db.Select<floorplan_room> |> first } |> db.Select<floorplan_room> |> first
let updateTablePosition (floorplanTable: floorplan_table) = Entity.updateInDatabase floorplanTable let updateTablePosition (floorplanTable: floorplan_table) = Entity.Update floorplanTable
let createEmptyReservation (reservation: reservation) = let createEmptyReservation (reservation: reservation) =
update { update {
table "floorplan_tables" table "floorplan_tables"
set {| status = 2 |} set {| status = 2 |}
where(eq "id" reservation.reservation_table_id) where(eq "id" reservation.floorplan_table_id)
} |> db.Update |> ignore } |> db.Update |> ignore
Entity.addToDatabase reservation Entity.Create reservation
let getChildTables tableNumber = let getChildTables tableNumber =
let table = getTable tableNumber let table = getTable tableNumber
@@ -165,7 +166,7 @@ let tableExists (tableNumber: int) =
match numberOfResults with match numberOfResults with
| 0 -> | 0 ->
let allTables = let allTables =
Entity.getAllInVenue<floorplan_table> Entity.GetAllInVenue<floorplan_table>
|> Array.map(findChildTable tableNumber) |> Array.map(findChildTable tableNumber)
|> Array.filter(fun tableNumber -> tableNumber <> 0) |> Array.filter(fun tableNumber -> tableNumber <> 0)
@@ -192,7 +193,7 @@ let addNewTableWithoutOutput (newTable: floorplan_table) =
} }
|> db.Insert |> db.Insert
let addNewTable (newTable: floorplan_table) = Entity.addToDatabase newTable let addNewTable (newTable: floorplan_table) = Entity.Create newTable
let mergeTables parent child = //Merge two tables together let mergeTables parent child = //Merge two tables together
if parent = child then false else if parent = child then false else
@@ -246,7 +247,7 @@ let mergeTables parent child = //Merge two tables together
where (eq "table_number" parent + eq "venue_id" (getCurrentVenue())) where (eq "table_number" parent + eq "venue_id" (getCurrentVenue()))
} |> db.Update |> ignore } |> db.Update |> ignore
Entity.deleteById<floorplan_table> newChildTable.id Entity.DeleteById<floorplan_table> newChildTable.id
|> ignore |> ignore
true true
@@ -289,30 +290,19 @@ let makeRoomButton (room: floorplan_room) =
Theme.loadTemplateWithVars "roomButton" vars Theme.loadTemplateWithVars "roomButton" vars
let getReservationList (tableList: floorplan_table[]) = let getReservationList (tableList: floorplan_table[]) =
let tableIds = tableList |> Array.collect Entity.GetAllRelated<reservation, floorplan_table>
tableList
|> Array.map(fun table -> box table.id)
|> List.ofArray
if tableIds.Length > 0 then
select {
table "reservations"
where (isIn "reservation_table_id" tableIds)
}
|> db.Select<reservation>
else [||]
let newReservation name time covers = let newReservation name time covers =
let reservation = { let reservation = {
id = 0 id = 0
reservation_name = name name = name
reservation_time = time time = time
reservation_covers = covers covers = covers
reservation_table_id = 0 floorplan_table_id = 0
reservation_created_at = CurrentTime() created_at = CurrentTime()
} }
Entity.addToDatabase reservation Entity.Create reservation
let tableList () = Entity.getAllInVenue<floorplan_table> let tableList () = Entity.GetAllInVenue<floorplan_table>

View File

@@ -2,13 +2,14 @@
open Dapper.FSharp open Dapper.FSharp
open DredgeFramework open DredgeFramework
open Pluralize.NET.Core open Pluralize.NET.Core
open FSharp.Reflection
let getDatabaseTable<'x> = let GetDatabaseTable<'x> =
let typeName = typeof<'x>.Name let typeName = typeof<'x>.Name
Pluralizer().Pluralize typeName Pluralizer().Pluralize typeName
let addToDatabase (record: 'x)= let Create (record: 'x)=
let tableName = getDatabaseTable<'x> let tableName = GetDatabaseTable<'x>
insert { insert {
table tableName table tableName
value record value record
@@ -18,42 +19,50 @@ let addToDatabase (record: 'x)=
|> first |> first
let inline updateInDatabase (record: ^x) = let inline Update (record: ^x) =
let tableName = getDatabaseTable<'x> let tableName = GetDatabaseTable<'x>
let id = ((^x) : (member id : int) (record)) let id = ((^x) : (member id : int) record)
update { update {
table tableName table tableName
set record set record
where (eq "id" id) where (eq "id" id)
excludeColumn "id"
} }
|> db.Update |> db.Update
let getAll<'x> = let GetAll<'x> =
let typeName = typeof<'x>.Name let tableName = GetDatabaseTable<'x>
let tableName = Pluralizer().Pluralize typeName
select { select {
table tableName table tableName
} }
|> db.Select<'x> |> db.Select<'x>
let getAllByColumn<'x> (column: string) (value: obj) = let GetAllByColumn<'x> (column: string) (value: obj) =
let typeName = typeof<'x>.Name let tableName = GetDatabaseTable<'x>
let tableName = Pluralizer().Pluralize typeName
select { select {
table tableName table tableName
where (eq column value) where (eq column value)
} |> db.Select<'x> } |> db.Select<'x>
let getAllInVenue<'x> = getAllByColumn<'x> "venue_id" (getCurrentVenue ()) let GetAllInVenue<'x> = GetAllByColumn<'x> "venue_id" (getCurrentVenue ())
let getById<'x> (id: int) = getAllByColumn<'x> "id" id |> first let GetById<'x> (id: int) = GetAllByColumn<'x> "id" id |> first
let deleteById<'x> id = let inline GetRelated<'x, .. > (entity: ^y) =
let columnName = typeof<'x>.Name + "_id"
let primaryKeyValue = typeof<'y>.GetProperty(columnName).GetValue(entity) :?> int
GetById<'x> primaryKeyValue
let inline GetAllRelated<'x, .. > (entity: ^y) =
let id = typeof<'y>.GetProperty("id").GetValue(entity) :?> int
let columnName = typeof<'y>.Name + "_id"
GetAllByColumn<'x> columnName id
let DeleteById<'x> id =
let typeName = typeof<'x>.Name let typeName = typeof<'x>.Name
let tableName = Pluralizer().Pluralize typeName let tableName = Pluralizer().Pluralize typeName
let entity = GetById<'x> id
let entity = getById<'x> id
delete { delete {
table tableName table tableName
@@ -61,3 +70,7 @@ let deleteById<'x> id =
} |> db.Delete |> ignore } |> db.Delete |> ignore
entity entity
let inline Delete< ^x when ^x: (member id: int) > (entity: ^x) =
typeof<'x>.GetProperty("id").GetValue(entity) :?> int
|> DeleteById<'x>

View File

@@ -4,16 +4,19 @@ open DredgePos
open DredgePos.Types open DredgePos.Types
open FSharp.Collections open FSharp.Collections
open Thoth.Json.Net open Thoth.Json.Net
open Types
open Theme open Theme
let getAllPageGrids () = Entity.getAllInVenue<order_screen_page_group> let getAllPageGrids () = Entity.GetAllInVenue<order_screen_page_group>
|> Array.filter(fun pageGroup -> pageGroup.grid_id <> 0) |> Array.filter(fun pageGroup -> pageGroup.grid_id <> 0)
|> Array.map(fun pageGroup -> (Entity.getById<grid> pageGroup.grid_id), pageGroup) |> Array.map(fun pageGroup -> (Entity.GetById<grid> pageGroup.grid_id), pageGroup)
let getImageButtonData (button: button) = let getImageButtonData (button: button) =
let item = Entity.getAllByColumn<item> "item_code" button.primary_action_value let itemCode =
if button.primary_action = "item" then button.primary_action_value
else button.secondary_action_value
let item = Entity.GetAllByColumn<item> "item_code" itemCode
|> first |> first
let extraData = let extraData =
@@ -26,9 +29,31 @@ let getImageButtonData (button: button) =
text = item.item_name text = item.item_name
|} |}
let getGridButtonData (button: button) =
let gridId =
if button.primary_action = "grid" then button.primary_action_value
else button.secondary_action_value
|> int
let grid = Entity.GetById<grid> gridId
{|
extra_data = map ["data-grid", jsonEncode gridId] |> htmlAttributes
text = grid.grid_name
|}
let getActionData (button: button) (action: string) =
let actionValue =
if action = "primary" then button.primary_action
else button.secondary_action
match actionValue with
| "item" -> getImageButtonData button
| "grid" -> getGridButtonData button
| "spacer" -> {|extra_data=""; text=""|}
| _ -> {|extra_data=""; text=""|}
let renderButton (buttonId: int) = let renderButton (buttonId: int) =
let button = Entity.getById<button> buttonId let button = Entity.GetById<button> buttonId
let extra_styles = let extra_styles =
match button.extra_styles.Length with match button.extra_styles.Length with
@@ -44,34 +69,36 @@ let renderButton (buttonId: int) =
let extraClasses = [|imageClass; spacerClass|] |> String.concat " " let extraClasses = [|imageClass; spacerClass|] |> String.concat " "
let action_data = let primary_action_data = getActionData button "primary"
match button.primary_action with let secondary_action_data = getActionData button "secondary"
| "item" -> getImageButtonData button
| "spacer" -> {|extra_data=""; text=""|} let action_extra_data = primary_action_data.extra_data + " " + secondary_action_data.extra_data
| _ -> {|extra_data=""; text=""|} let button_text =
if button.text.Length > 0 then button.text
else
if primary_action_data.text.Length > 0 then primary_action_data.text
else secondary_action_data.text
let vars = map [ let vars = map [
"extra_classes", button.extra_classes + " " + extraClasses "extra_classes", button.extra_classes + " " + extraClasses
"extra_styles", extra_styles "extra_styles", extra_styles
"primary_action", button.primary_action "primary_action", button.primary_action
"secondary_action", button.secondary_action "secondary_action", button.secondary_action
"text", if button.text.Length > 0 then button.text else action_data.text "text", button_text
"image", image "image", image
"extra_data", action_data.extra_data "extra_data", action_extra_data
] ]
loadTemplateWithVars "orderScreen/grid_button" vars loadTemplateWithVars "orderScreen/grid_button" vars
let renderPage (buttonHTML: string) = let renderPage (grid: grid) (buttonHTML: string) =
let vars = map [ let vars = map ["pageButtons", buttonHTML; "rows", string grid.grid_rows; "cols", string grid.grid_cols]
"pageButtons", buttonHTML
]
loadTemplateWithVars "orderScreen/page" vars loadTemplateWithVars "orderScreen/page" vars
let renderPageGroup (pageGroup: order_screen_page_group) (pageHTML: string) = let renderPageGroup (pageGroup: order_screen_page_group) (pageHTML: string) =
let vars = map [ let vars = map [
"pages", pageHTML "pages", pageHTML
"page_group_id", pageGroup.id.ToString() "page_group_id", string pageGroup.id
] ]
loadTemplateWithVars "orderScreen/page_group" vars loadTemplateWithVars "orderScreen/page_group" vars
@@ -79,24 +106,32 @@ let printGroupPosButton (printGroup: print_group) =
PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """ PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """
let generateSalesCategoryOverrideButtons () = let generateSalesCategoryOverrideButtons () =
Entity.getAllInVenue<print_group> Entity.GetAllInVenue<print_group>
|> Array.map printGroupPosButton |> Array.map printGroupPosButton
|> Array.append ([|PosButton (language.getAndReplace "print_with" ["default"]) "printGroupOverrideButton toggle default active" """data-value="0" """|]) |> Array.append [|PosButton (language.getAndReplace "print_with" ["default"]) "printGroupOverrideButton toggle default active" """data-value="0" """|]
|> String.concat "\n" |> String.concat "\n"
let renderGrid (grid: grid) =
let gridData = grid.grid_data |> Decode.Auto.fromString<Map<string, int[]>>
match gridData with
| Error _ -> "Error"
| Ok pages ->
pages
|> Map.toArray
|> Array.map snd
|> Array.map(fun row -> row |> Array.map renderButton |> String.concat "\n")
|> Array.map (renderPage grid)
|> String.concat "\n"
let loadGrid gridId = renderGrid (Entity.GetById<grid> gridId)
let getPagesHTML (gridInfo: grid * order_screen_page_group) = let getPagesHTML (gridInfo: grid * order_screen_page_group) =
let grid, pageGroup = gridInfo let grid, pageGroup = gridInfo
let pages = grid.grid_data |> Decode.Auto.fromString<Map<string, int[]>> renderGrid grid
|> renderPageGroup pageGroup
match pages with
| Error _ -> "Error"
| Ok pages ->
pages
|> Map.toArray
|> Array.map snd
|> Array.map(fun row -> row |> Array.map renderButton |> String.concat "\n")
|> Array.map renderPage
|> String.concat "\n"
|> renderPageGroup pageGroup

View File

@@ -20,7 +20,7 @@ let loadFloorplan (ctx: HttpContext) : HttpHandler =
Session.RequireClerkAuthentication ctx Session.RequireClerkAuthentication ctx
let roomMenu = let roomMenu =
Entity.getAllInVenue<floorplan_room> Entity.GetAllInVenue<floorplan_room>
|> Array.map makeRoomButton |> Array.map makeRoomButton
|> String.concat "\n" |> String.concat "\n"
@@ -43,14 +43,20 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
let covers = if tableNumber > 0 then (getTable tableNumber).default_covers else 0 let covers = if tableNumber > 0 then (getTable tableNumber).default_covers else 0
let coverString = language.getAndReplace "covers" [covers] let coverString = language.getAndReplace "covers" [covers]
let coverSelectorButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/cover_selector_button" (map ["covers", coverString]) else "" let changeCoverNumberButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/change_cover_number_button" (map ["covers", coverString]) else ""
let orderNumber = let orderNumber =
if tableNumber > 0 then language.getAndReplace "active_table" [tableNumber] if tableNumber > 0 then language.getAndReplace "active_table" [tableNumber]
else language.get "new_order" else language.get "new_order"
let containerAttributes =
if tableNumber > 0 then
map ["data-table", jsonEncode (getTable tableNumber)]
|> Theme.htmlAttributes
else ""
let categoryList = let categoryList =
Entity.getAllInVenue<order_screen_page_group> Entity.GetAllInVenue<order_screen_page_group>
|> Array.filter (fun page_group -> page_group.id <> 0) |> Array.filter (fun page_group -> page_group.id <> 0)
|> Array.sortBy (fun {order=order} -> order) |> Array.sortBy (fun {order=order} -> order)
|> Array.map (fun category -> |> Array.map (fun category ->
@@ -65,22 +71,24 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
|> Array.map OrderScreen.getPagesHTML |> Array.map OrderScreen.getPagesHTML
|> String.concat "\n" |> String.concat "\n"
let customItem = let coverSelectorButtons =
Entity.getAllByColumn<item> "item_code" "OPEN000" Array.init (covers+1) id
|> filterFirst |> Array.map(fun coverNumber ->
|> Array.map jsonEncode let text = if coverNumber > 0 then language.getAndReplace "selected_cover" [coverNumber]
|> String.concat "" else language.get "cover_zero"
Theme.PosButton text "coverSelectorButton" $"""data-cover="{coverNumber}" """)
|> String.concat "\n"
let variables = map [ let variables = map [
"title", "Order" "title", "Order"
"containerAttributes", containerAttributes
"categoryList", categoryList "categoryList", categoryList
"pageGroups", grids "pageGroups", grids
"orderNumber", orderNumber "orderNumber", orderNumber
"coverSelectorButton", coverSelectorButton "changeCoverNumberButton", changeCoverNumberButton
"covers", coverString "covers", coverString
"salesCategoryOverrideButtons", OrderScreen.generateSalesCategoryOverrideButtons () "salesCategoryOverrideButtons", OrderScreen.generateSalesCategoryOverrideButtons ()
"custom", OrderScreen.generateSalesCategoryOverrideButtons () "coverSelectorButtons", coverSelectorButtons
] ]
let styles = ["dredgepos.orderScreen.css"] let styles = ["dredgepos.orderScreen.css"]
@@ -88,7 +96,8 @@ let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
let currentClerk = recordToMap <| Session.getCurrentClerk ctx let currentClerk = recordToMap <| Session.getCurrentClerk ctx
let arrays = map ["clerk", currentClerk] let arrays = map ["clerk", currentClerk]
htmlString <| Theme.loadTemplateWithVarsArraysScriptsAndStyles "orderScreen" variables arrays scripts styles Theme.loadTemplateWithVarsArraysScriptsAndStyles "orderScreen" variables arrays scripts styles
|> htmlString
let getOpenTables() = let getOpenTables() =
let rows = openTables() let rows = openTables()

View File

@@ -2,6 +2,7 @@ namespace WebApplication
open DredgePos open DredgePos
open DredgePos.Types
open Microsoft.AspNetCore.Server.Kestrel.Core open Microsoft.AspNetCore.Server.Kestrel.Core
open Reservations open Reservations
open Saturn open Saturn
@@ -40,10 +41,11 @@ module Program =
getf "/unmergeTable/%i" AjaxController.unmergeTable getf "/unmergeTable/%i" AjaxController.unmergeTable
getf "/tableExists/%i" (fun tableNumber -> json <| Floorplan.tableExists tableNumber) getf "/tableExists/%i" (fun tableNumber -> json <| Floorplan.tableExists tableNumber)
} }
let orderScreenRouter = router { let orderScreenRouter = router {
pipe_through browser pipe_through browser
getf "/getOrderScreenData/%i" AjaxController.getOrderScreenData getf "/getOrderScreenData/%i" AjaxController.getOrderScreenData
getf "/getGridHtml/%i" AjaxController.loadGrid
post "/updateCovers" (bindJson<floorplan_table> (fun table -> Entity.Update table |> Array.head |> DredgeFramework.ajaxSuccess |> json))
} }
let pageRouter = router { let pageRouter = router {

View File

@@ -49,7 +49,7 @@ let ParseVariables (varArray: Map<string, string>) (html:string) =
if varName |> ToLowerCase = "title" then titlePrefix varArray[varName] if varName |> ToLowerCase = "title" then titlePrefix varArray[varName]
else varArray[varName] else varArray[varName]
else else
"<!--[Undefined Variable: " + varName + "]-->" ""
)) ))
let ParseArrays (arrayArray: Map<string, Map<string, string>>) (string:string) = let ParseArrays (arrayArray: Map<string, Map<string, string>>) (string:string) =

View File

@@ -3,11 +3,17 @@ module DredgePos.Types
[<CLIMutable>] [<CLIMutable>]
type reservation = { type reservation = {
id: int id: int
reservation_name: string name: string
reservation_time: int time: int
reservation_covers: int covers: int
reservation_table_id: int floorplan_table_id: int
reservation_created_at: int created_at: int
}
[<CLIMutable>]
type venue = {
id: int
venue_name: string
} }
[<CLIMutable>] [<CLIMutable>]

View File

@@ -45,8 +45,6 @@ const ajax = (endpoint: string, data: any, method = 'POST', successFunction: Fun
beforeSend: beforeFunction beforeSend: beforeFunction
}) })
} }
/* /*
For the flow of the app, synchronous is commonly preferred For the flow of the app, synchronous is commonly preferred
though trying to keep its usage as low as possible. though trying to keep its usage as low as possible.
@@ -229,5 +227,13 @@ function* newestId(){
} }
} }
const loadTemplate = (templateSelector: string) => {
const content = $(templateSelector)
.clone()
.removeAttr('id')
.prop('content')
return $(content)
}
$(() => ajax('/ajax/languageVars', null, 'GET', setupCore, null, null)) $(() => ajax('/ajax/languageVars', null, 'GET', setupCore, null, null))

View File

@@ -10,7 +10,7 @@ interface floorplan{
transformer: Konva.Transformer transformer: Konva.Transformer
tableLayer: Konva.Layer tableLayer: Konva.Layer
rooms: room[] rooms: room[]
tables: table[] tables: floorplan_table[]
decorations: decoration[] decorations: decoration[]
activeTableNumbers: number[] activeTableNumbers: number[]
selectedTableNumber: number selectedTableNumber: number
@@ -24,7 +24,7 @@ interface floorplan{
} }
interface floorplan_data{ interface floorplan_data{
tables: table[] tables: floorplan_table[]
decorations: decoration[] decorations: decoration[]
activeTableNumbers: number[] activeTableNumbers: number[]
rooms: room[] rooms: room[]
@@ -137,9 +137,9 @@ const getRoomById = (roomId: number) => {
) )
} }
const tableIsOpen = (table: table) => Floorplan.activeTableNumbers.includes(table.table_number) const tableIsOpen = (table: floorplan_table) => Floorplan.activeTableNumbers.includes(table.table_number)
const createTableShape = (table: table) => { const createTableShape = (table: floorplan_table) => {
const draggable = isInMode('edit') const draggable = isInMode('edit')
const tableGroup = new Konva.Group({ const tableGroup = new Konva.Group({
@@ -243,7 +243,7 @@ const saveTableTransformation = (tableGroup: Konva.Group) => {
const originalTable = getTableDataFromGroup(tableGroup) const originalTable = getTableDataFromGroup(tableGroup)
const tableShape = getTableShapeFromGroup(tableGroup) const tableShape = getTableShapeFromGroup(tableGroup)
const newTableInfo : table = { const newTableInfo : floorplan_table = {
table_number : originalTable.table_number, table_number : originalTable.table_number,
previous_state : originalTable.previous_state, previous_state : originalTable.previous_state,
merged_children : originalTable.merged_children, merged_children : originalTable.merged_children,
@@ -265,7 +265,7 @@ const saveTableTransformation = (tableGroup: Konva.Group) => {
} }
const saveTable = (tableToUpdate: table) => { const saveTable = (tableToUpdate: floorplan_table) => {
const tables = const tables =
Floorplan Floorplan
.tables .tables
@@ -309,20 +309,20 @@ const getTableGroupFromTableNumber = (tableNumber : number) => {
return getTableGroupFromShape(tableShape) return getTableGroupFromShape(tableShape)
} }
const setReservationStatus = (table: table) => { const setReservationStatus = (table: floorplan_table) => {
const reservationText = $('.reservationStatus') const reservationText = $('.reservationStatus')
const tableShape = getTableShapeFromTableNumber(table.table_number) const tableShape = getTableShapeFromTableNumber(table.table_number)
reservationText.text('') reservationText.text('')
if(table.status == 2) { if(table.status == 2) {
tableShape.fill('lightgreen') tableShape.fill('lightgreen')
const reservations = Floorplan.reservations.filter(reservation => reservation.reservation_table_id == table.id) const reservations = Floorplan.reservations.filter(reservation => reservation.floorplan_table_id == table.id)
if (reservations.length) { if (reservations.length) {
turnOnMode('reservedTableSelected') turnOnMode('reservedTableSelected')
reservationText.text(lang('reserved')) reservationText.text(lang('reserved'))
let reservation = reservations[0] let reservation = reservations[0]
if (reservation.reservation_name != '') { if (reservation.name != '') {
reservationText.text(lang('reserved_for', reservation.reservation_name)) reservationText.text(lang('reserved_for', reservation.name))
} }
} }
} else { } else {
@@ -340,11 +340,11 @@ const reserveTable = () => {
const createEmptyReservation = (covers: number) => { const createEmptyReservation = (covers: number) => {
const newReservation: reservation = { const newReservation: reservation = {
id: 0, id: 0,
reservation_covers: covers, covers: covers,
reservation_created_at: 0, created_at: 0,
reservation_table_id: getSelectedTableData().id, floorplan_table_id: getSelectedTableData().id,
reservation_name: '', name: '',
reservation_time: 0, time: 0,
} }
ajax('/ajax/newEmptyReservation', newReservation,'post', emptyReservationCreated, null, null ) ajax('/ajax/newEmptyReservation', newReservation,'post', emptyReservationCreated, null, null )
@@ -354,7 +354,7 @@ const emptyReservationCreated = (reservation: reservation) => {
Floorplan.reservations.push(reservation) Floorplan.reservations.push(reservation)
const selectedTable = getSelectedTableData() const selectedTable = getSelectedTableData()
selectedTable.status = 2 selectedTable.status = 2
selectedTable.default_covers = reservation.reservation_covers selectedTable.default_covers = reservation.covers
updateTableData(selectedTable) updateTableData(selectedTable)
updateCoverText(selectedTable) updateCoverText(selectedTable)
setReservationStatus(getSelectedTableData()) setReservationStatus(getSelectedTableData())
@@ -364,8 +364,8 @@ const emptyReservationCreated = (reservation: reservation) => {
const addReservationName = (name: string) => { const addReservationName = (name: string) => {
hideVirtualKeyboard() hideVirtualKeyboard()
const reservation = Floorplan.reservations.filter(reservation => reservation.reservation_table_id == getSelectedTableData().id)[0] const reservation = Floorplan.reservations.filter(reservation => reservation.floorplan_table_id == getSelectedTableData().id)[0]
reservation.reservation_name = name reservation.name = name
ajax('/ajax/updateReservation', reservation, 'post', reservationNameAdded, null, null) ajax('/ajax/updateReservation', reservation, 'post', reservationNameAdded, null, null)
} }
@@ -376,9 +376,9 @@ const reservationNameAdded = (updatedReservation: reservation) => {
setReservationStatus(getSelectedTableData()) setReservationStatus(getSelectedTableData())
} }
const getReservationsOnTable = (table: table) => Floorplan.reservations.filter(reservation => reservation.reservation_table_id == table.id) const getReservationsOnTable = (table: floorplan_table) => Floorplan.reservations.filter(reservation => reservation.floorplan_table_id == table.id)
const updateTableData = (tableToRemove: table) => { const updateTableData = (tableToRemove: floorplan_table) => {
Floorplan.tables = Floorplan.tables.filter(table => table.id != tableToRemove.id) Floorplan.tables = Floorplan.tables.filter(table => table.id != tableToRemove.id)
Floorplan.tables.push(tableToRemove) Floorplan.tables.push(tableToRemove)
} }
@@ -389,8 +389,8 @@ const unreserveTable = () => {
ajax('/ajax/unreserveTable', selectedTable, 'post', tableUnreserved, null, null) ajax('/ajax/unreserveTable', selectedTable, 'post', tableUnreserved, null, null)
} }
const tableUnreserved = (table: table) => { const tableUnreserved = (table: floorplan_table) => {
Floorplan.reservations = Floorplan.reservations.filter(reservation => reservation.reservation_table_id != table.id) Floorplan.reservations = Floorplan.reservations.filter(reservation => reservation.floorplan_table_id != table.id)
updateTableData(table) updateTableData(table)
setReservationStatus(table) setReservationStatus(table)
} }
@@ -438,7 +438,7 @@ const selectTable = (tableShape: Konva.Shape) => {
turnOnMode('tableSelected') turnOnMode('tableSelected')
} }
const updateCoverText = (table:table) => $('.selectedTableCovers').text(lang('covers', table.default_covers.toString())) const updateCoverText = (table:floorplan_table) => $('.selectedTableCovers').text(lang('covers', table.default_covers.toString()))
const tableDblClicked = (event: Konva.KonvaEventObject<any>) => { const tableDblClicked = (event: Konva.KonvaEventObject<any>) => {
let tableShape = getTableShapeFromGroup(event.currentTarget as Konva.Group) let tableShape = getTableShapeFromGroup(event.currentTarget as Konva.Group)
@@ -718,7 +718,7 @@ const redrawTable = (tableGroup: Konva.Group) => {
const showAddTablePopup = () => showVirtualNumpad(lang('new_table_number'), 4, false, false, true, addTable); const showAddTablePopup = () => showVirtualNumpad(lang('new_table_number'), 4, false, false, true, addTable);
const addTable = (tableNumber: number) => { const addTable = (tableNumber: number) => {
const newTable : table = { const newTable : floorplan_table = {
id: 0, id: 0,
table_number: tableNumber, table_number: tableNumber,
room_id: Floorplan.currentRoom.id, room_id: Floorplan.currentRoom.id,
@@ -738,7 +738,7 @@ const addTable = (tableNumber: number) => {
ajax('/ajax/createTable', newTable, 'post', tableAdded, tableNotAdded, null) ajax('/ajax/createTable', newTable, 'post', tableAdded, tableNotAdded, null)
} }
const tableAdded = (table: table) => { const tableAdded = (table: floorplan_table) => {
deselectTables() deselectTables()
const newTableGroup = createTableShape(table) const newTableGroup = createTableShape(table)
Floorplan.tables.push(table) Floorplan.tables.push(table)
@@ -766,7 +766,7 @@ const deleteTable = (tableNumber: number) => {
ajax(`/ajax/deleteTable`, tableToDelete, 'post', tableDeleted, null, null); ajax(`/ajax/deleteTable`, tableToDelete, 'post', tableDeleted, null, null);
} }
const tableDeleted = (deletedTable: table) => { const tableDeleted = (deletedTable: floorplan_table) => {
Floorplan.tables = Floorplan.tables.filter(table => table.table_number != deletedTable.table_number) Floorplan.tables = Floorplan.tables.filter(table => table.table_number != deletedTable.table_number)
const tableGroup = getTableGroupFromTableNumber(deletedTable.table_number) const tableGroup = getTableGroupFromTableNumber(deletedTable.table_number)
deselectTables() deselectTables()
@@ -776,7 +776,7 @@ const tableDeleted = (deletedTable: table) => {
const toggleMergeMode = () => toggleMode('merge') const toggleMergeMode = () => toggleMode('merge')
const mergeTables = (table1: table, table2: table ) => { const mergeTables = (table1: floorplan_table, table2: floorplan_table ) => {
toggleMergeMode() toggleMergeMode()
if(table1.table_number == table2.table_number){ if(table1.table_number == table2.table_number){
posAlert(lang('error_self_merge')) posAlert(lang('error_self_merge'))
@@ -785,7 +785,7 @@ const mergeTables = (table1: table, table2: table ) => {
ajax('/ajax/mergeTables', [table1, table2], 'post', tablesMerged, null, null) ajax('/ajax/mergeTables', [table1, table2], 'post', tablesMerged, null, null)
} }
const tablesMerged = (tables: Record<'child'|'parent'|'merged', table>) => { const tablesMerged = (tables: Record<'child'|'parent'|'merged', floorplan_table>) => {
tableDeleted(tables['child']) tableDeleted(tables['child'])
tableDeleted(tables['parent']) tableDeleted(tables['parent'])
tableAdded(tables['merged']) tableAdded(tables['merged'])
@@ -797,7 +797,7 @@ const tablesMerged = (tables: Record<'child'|'parent'|'merged', table>) => {
const unmergeTable = () => ajax(`/ajax/unmergeTable/${Floorplan.selectedTableNumber}`, null, 'get', tablesUnmerged, null, null) const unmergeTable = () => ajax(`/ajax/unmergeTable/${Floorplan.selectedTableNumber}`, null, 'get', tablesUnmerged, null, null)
const tablesUnmerged = (tables: Record<'child'|'parent', table>) => { const tablesUnmerged = (tables: Record<'child'|'parent', floorplan_table>) => {
const parentTable = tables['parent'] const parentTable = tables['parent']
const childTable = tables['child'] const childTable = tables['child']
@@ -809,7 +809,7 @@ const tablesUnmerged = (tables: Record<'child'|'parent', table>) => {
const toggleTransferMode = () => toggleMode('transfer') const toggleTransferMode = () => toggleMode('transfer')
const transferTables = (origin: table, destination: table) => { const transferTables = (origin: floorplan_table, destination: floorplan_table) => {
if(origin.table_number == destination.table_number){ if(origin.table_number == destination.table_number){
posAlert(lang('transfer_self_error')) posAlert(lang('transfer_self_error'))
return return
@@ -818,7 +818,7 @@ const transferTables = (origin: table, destination: table) => {
ajax(`/ajax/transferTable/${origin.table_number}/${destination.table_number}`, null, 'get', tableTransferred, null, null) ajax(`/ajax/transferTable/${origin.table_number}/${destination.table_number}`, null, 'get', tableTransferred, null, null)
} }
const tableTransferred = (tables: Record<"origin"|"destination", table>) => { const tableTransferred = (tables: Record<"origin"|"destination", floorplan_table>) => {
const origin = tables['origin'] const origin = tables['origin']
const destination = tables['destination'] const destination = tables['destination']

View File

@@ -16,6 +16,8 @@ type OrderScreen = {
qty_override: number qty_override: number
print_group_override: print_group print_group_override: print_group
custom_item: item, custom_item: item,
selected_cover: number
table: floorplan_table,
} }
let OrderScreen : OrderScreen = { let OrderScreen : OrderScreen = {
@@ -28,17 +30,24 @@ let OrderScreen : OrderScreen = {
selected_item_ids: [], selected_item_ids: [],
qty_override: 1, qty_override: 1,
print_group_override: null, print_group_override: null,
custom_item: null custom_item: null,
selected_cover: 0,
table: null,
} }
const loadPageGroup = (e: Event) => { const loadPageGroup = (e: Event) => {
let button = $(e.target) const button = $(e.target)
const container = $('#pageGroupContainer')
$('.loadPageGroup').removeClass('active') $('.loadPageGroup').removeClass('active')
button.addClass('active') button.addClass('active')
let pageGroupId = button.data('page-group-id') let pageGroupId = button.data('page-group-id')
$('.pageGroup').hide()
container.find('.pageGroup').hide()
let activeGrid = $(`.pageGroup[data-page-group-id=${pageGroupId}]`) let activeGrid = $(`.pageGroup[data-page-group-id=${pageGroupId}]`)
let navButtons = $('.pageNavigation') let navButtons = container.next('.pageNavigation')
navButtons.css('display', 'flex') navButtons.css('display', 'flex')
activeGrid.find('.gridPage').length > 1 activeGrid.find('.gridPage').length > 1
@@ -49,6 +58,9 @@ const loadPageGroup = (e: Event) => {
} }
const setupOrderScreen = (data: OrderScreenData) => { const setupOrderScreen = (data: OrderScreenData) => {
$('.coverSelector, .gridContainer').hide()
OrderScreen.order_screen_pages = data.order_screen_pages OrderScreen.order_screen_pages = data.order_screen_pages
OrderScreen.sales_categories = data.sales_categories OrderScreen.sales_categories = data.sales_categories
OrderScreen.print_groups = data.print_groups OrderScreen.print_groups = data.print_groups
@@ -60,6 +72,8 @@ const setupOrderScreen = (data: OrderScreenData) => {
doc.on('click', '.prevButton', goToPrevPage) doc.on('click', '.prevButton', goToPrevPage)
doc.on('click', '.loadPageGroup', loadPageGroup) doc.on('click', '.loadPageGroup', loadPageGroup)
doc.on('click', '[data-primary-action=item]', itemButtonClicked) doc.on('click', '[data-primary-action=item]', itemButtonClicked)
doc.on('click', '[data-primary-action=grid],[data-secondary-action=grid]', gridButtonClicked)
doc.on('click', '.closeGrid', hideGrids)
doc.on('click', '.freetextButton', freetext) doc.on('click', '.freetextButton', freetext)
doc.on('click', '.openItemButton', customItem) doc.on('click', '.openItemButton', customItem)
doc.on('click', '.orderBoxTable tbody tr', itemRowClicked) doc.on('click', '.orderBoxTable tbody tr', itemRowClicked)
@@ -67,6 +81,9 @@ const setupOrderScreen = (data: OrderScreenData) => {
doc.on('dblclick', '.voidButton', voidLastItem) doc.on('dblclick', '.voidButton', voidLastItem)
doc.on('click', '.numpadButton', overrideQty) doc.on('click', '.numpadButton', overrideQty)
doc.on('click', '.accumulateButton', () => toggleMode('accumulate')) doc.on('click', '.accumulateButton', () => toggleMode('accumulate'))
doc.on('click', '.changeCoverNumberButton', changeCoverNumberPrompt)
doc.on('click', '.showCoverSelectorButton', showCoverSelector)
doc.on('click', '.coverSelectorButton', coverSelected)
doc.on('change', '[name=print_override]', printGroupOverride) doc.on('change', '[name=print_override]', printGroupOverride)
turnOnMode('accumulate') turnOnMode('accumulate')
@@ -85,23 +102,29 @@ const setupOrderScreen = (data: OrderScreenData) => {
/** /**
* @param direction 1 for forward, -1 for backwards. * @param direction 1 for forward, -1 for backwards.
* @param button
*/ */
const navigatePage = (direction: number) => { const navigatePage = (direction: number, button: JQuery) => {
let grid = $('.pageGroup:visible') const grid =
button
.parent()
.parent()
.find('.pageGroup:visible')
grid.get()[0].scrollLeft += grid.width() * direction grid.get()[0].scrollLeft += grid.width() * direction
} }
const goToNextPage = () => navigatePage(1) const goToNextPage = (e: JQuery.TriggeredEvent) => navigatePage(1, $(e.target))
const goToPrevPage = () => navigatePage(-1) const goToPrevPage = (e: JQuery.TriggeredEvent) => navigatePage(-1, $(e.target))
const addItemToOrderBox = (orderItem:orderItem) => { const addItemToOrderBox = (orderItem:orderItem) => {
const orderBox = $('.orderBoxTable tbody') const orderBox = $('.orderBoxTable tbody')
let selectedRows = orderBox.find('tr.selected') let selectedRows = orderBox.find('tr.selected')
let lastRow : JQuery = selectedRows.length ? selectedRows.first() : orderBox.find('tr').last() let lastRow : JQuery = selectedRows.length ? getLastInstructionRow(selectedRows.first()) : orderBox.find('tr').last()
const existingRow = orderBox const existingRow = orderBox
.find('tr') .find('tr')
.filterByData('item', orderItem.item) .filterByData('item', orderItem.item)
.filterByData('print_group', orderItem.print_group) .filterByData('print_group', orderItem.print_group)
.filterByData('cover', orderItem.cover)
.last() .last()
@@ -137,16 +160,28 @@ const addInstructionToOrderBox = (instruction: orderItem) => {
const parentRow = getParentRow(selectedRow) const parentRow = getParentRow(selectedRow)
if(parentRow.is(selectedRow) || !parentRow.hasClass('selected')) { if(parentRow.is(selectedRow) || !parentRow.hasClass('selected')) {
const newRow = createOrderRow(instruction) const newRow = createOrderRow(instruction)
getLastInstructionRow(selectedRow).after(newRow.pulse()) getLastInstructionRow(selectedRow).after(newRow)
newRow.setColumnValue(lang('printgroup_header'), selectedRow.getColumnValue(lang('printgroup_header'))) newRow
.setColumnValue( lang('printgroup_header'), selectedRow.getColumnValue(lang('printgroup_header')) )
if(parentRow.hasClass('selected')){
selectRow(newRow)
} else {
newRow.pulse()
}
scrollToElement(newRow)
} }
}) })
return
} }
const lastRow = orderBox.find('tr').last() const lastRow = orderBox.find('tr').last()
orderBox.append(newRow.pulse()) newRow
newRow.setColumnValue(lang('printgroup_header'), lastRow.getColumnValue(lang('printgroup_header'))) .setColumnValue(lang('printgroup_header'), lastRow.getColumnValue(lang('printgroup_header')))
.appendTo(orderBox)
.pulse()
scrollToElement(newRow)
} }
@@ -158,6 +193,7 @@ const addNewItem = (item: item, qty = 1) => {
item: item, item: item,
qty: qty, qty: qty,
print_group: printGroup, print_group: printGroup,
cover: OrderScreen.selected_cover,
} }
switch(item.item_type){ switch(item.item_type){
@@ -222,19 +258,23 @@ const renderOrderBox = () => {
const createOrderRow = (orderItem: orderItem) => { const createOrderRow = (orderItem: orderItem) => {
const row = $('.orderBoxTable').EmptyRow() const row = $('.orderBoxTable').EmptyRow()
const price = money(orderItem.item.price1) const price = money(orderItem.item.price1)
row.data('order-item-id', orderItem.id) const itemCellText = $('<span/>').text(orderItem.item.item_name)
row.addClass(`${orderItem.item.item_type}Row`)
row row
.addClass(`${orderItem.item.item_type}Row`)
.setColumnValue(lang('qty_header'), orderItem.qty) .setColumnValue(lang('qty_header'), orderItem.qty)
.setColumnValue(lang('item_header'), orderItem.item.item_name)
.setColumnValue(lang('price_header'), price) .setColumnValue(lang('price_header'), price)
.setColumnValue(lang('id_header'), orderItem.item.id) .setColumnValue(lang('id_header'), orderItem.item.id)
.setColumnValue(lang('total_price_header'), price.multiply(orderItem.qty)) .setColumnValue(lang('total_price_header'), price.multiply(orderItem.qty))
.setColumnValue(lang('printgroup_header'), orderItem.print_group?.name) .setColumnValue(lang('printgroup_header'), orderItem.print_group?.name)
.data('order-item-id', orderItem.id) .data('order-item-id', orderItem.id)
.data('order-item-id', orderItem.id)
.data('print_group', orderItem.print_group) .data('print_group', orderItem.print_group)
.data('cover', orderItem.cover)
.data('item', orderItem.item) .data('item', orderItem.item)
.find('td.itemCell')
.append(itemCellText)
changeCoverOnRow(row, orderItem.cover)
if(orderItem.item.item_type == 'instruction' && price.value <= 0){ if(orderItem.item.item_type == 'instruction' && price.value <= 0){
row row
@@ -246,6 +286,7 @@ const createOrderRow = (orderItem: orderItem) => {
} }
const itemButtonClicked = (e: JQuery.TriggeredEvent) => { const itemButtonClicked = (e: JQuery.TriggeredEvent) => {
hideGrids()
const existingItemRows = $('.itemRow') const existingItemRows = $('.itemRow')
const button = $(e.target).closest('.posButton') const button = $(e.target).closest('.posButton')
const item : item = button.data('item') const item : item = button.data('item')
@@ -259,6 +300,41 @@ const itemButtonClicked = (e: JQuery.TriggeredEvent) => {
} }
const gridButtonClicked = (e: JQuery.TriggeredEvent) => {
const button = $(e.target).closest('.posButton')
const grid : number = button.data('grid')
ajax(`/orderScreen/getGridHtml/${grid}`, null, null,gridHtmlGenerated, null, null)
}
const hideGrids = () => $('.gridContainer').hide()
const gridHtmlGenerated = (gridData: {gridHtml:string, grid: grid}) => {
const gridContainer = $('.gridContainer')
const gridCellWidth = getGridCellWidth()
const gridCellHeight = getGridCellHeight()
const grid = gridData.grid
const gridHtml = gridData.gridHtml
gridContainer
.show()
.width(gridCellWidth * grid.grid_cols)
.children('.gridContainerHeader')
.children('span')
.text(grid.grid_name)
.parent()
.parent()
.find('.pageGroup')
.html(gridHtml)
.show()
.parent()
.height(gridCellHeight * grid.grid_rows)
.closest('.gridContainer')
.find('.pageNavigation')
.toggle(gridContainer.find('.gridPage').length > 1)
.height(gridCellHeight)
}
const itemRowClicked = (e: JQuery.TriggeredEvent) => { const itemRowClicked = (e: JQuery.TriggeredEvent) => {
const row = $(e.target).closest('tr') const row = $(e.target).closest('tr')
@@ -369,7 +445,19 @@ const decrementQty = (row: JQuery, qty=1) => {
calculateRowTotal(row) calculateRowTotal(row)
} }
const scrollToElement = (element: JQuery) => element.get()[0].scrollIntoView() const scrollToElement = (JQueryElement: JQuery) => {
const element = JQueryElement.get()[0]
const container = JQueryElement.closest('.orderBox').get()[0]
const containerTop = $(container).scrollTop()
const containerBottom = containerTop + $(container).height();
const elemTop = element.offsetTop
const elemBottom = elemTop + $(element).height();
if (elemTop < containerTop) {
$(container).scrollTop(elemTop);
} else if (elemBottom > containerBottom) {
$(container).scrollTop(elemBottom - $(container).height());
}
}
const overrideQty = () => showVirtualNumpad(lang('multiplier'), 4, false, true, true, qtyOverridden) const overrideQty = () => showVirtualNumpad(lang('multiplier'), 4, false, true, true, qtyOverridden)
@@ -429,4 +517,88 @@ const customItemTextSubmitted = (text: string) => {
showVirtualNumpad(lang('enter_item_price'), 4, false, true, true, submitFunction) showVirtualNumpad(lang('enter_item_price'), 4, false, true, true, submitFunction)
} }
$(() => ajax('/orderScreen/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null) ) const getGridCellHeight = () => $('#pageGroupContainer').height()/8
const getGridCellWidth = () => $('#pageGroupContainer').width()/6
const showCoverSelector = (event: JQuery.TriggeredEvent) => {
const button = $(event.target)
const gridHeight = getGridCellHeight()
const coverSelector = $('.coverSelector')
coverSelector
.toggle(!coverSelector.is(':visible'))
.width(button.width())
.css({
left: button.offset().left + 'px',
top: button.offset().top + button.height() + 'px',
})
.find('.coverSelectorButton')
.height(gridHeight)
}
const coverSelected = (event: JQuery.TriggeredEvent) => {
$('.coverSelector').hide()
const button = $(event.target)
const cover = Number(button.data('cover'))
const selectedRows = $('.orderBoxTable tbody').find('tr.itemRow.selected')
selectedRows.each( (_, selectedRow) => changeCoverOnRow($(selectedRow), cover))
OrderScreen.selected_cover = cover
}
const changeCoverOnRow = (row: JQuery, cover: number) => {
row.data('cover', cover)
const itemCell = row.find('.itemCell')
const existingCoverSpan = itemCell.find('small')
const coverSpan = existingCoverSpan.length > 0
? existingCoverSpan
: $('<small/>').appendTo(itemCell)
coverSpan.text(lang('selected_cover', cover.toString()))
if(cover < 1 || !row.hasClass('itemRow')) {
coverSpan.remove()
}
}
const changeCoverNumberPrompt = () =>
showVirtualNumpad(lang('how_many_covers'), 3, false, false, true, changeCoverNumberPromptSubmitted)
const changeCoverNumberPromptSubmitted = (value: string) => updateCoverNumbers(Number(value))
const updateCoverNumbers = (covers: number) => {
let newTable = Object.assign({}, OrderScreen.table)
newTable.default_covers = covers
ajax('/orderScreen/updateCovers', newTable, 'post', coverNumbersUpdated, null, null)
}
const coverNumbersUpdated = (newTable: floorplan_table) => {
const covers = newTable.default_covers
OrderScreen.table = newTable
$('.changeCoverNumberButton').text(lang('covers', covers.toString()))
generateCoverSelector()
}
const generateCoverSelector = () => {
const covers = OrderScreen.table.default_covers
const coverSelector = $('.coverSelector')
coverSelector.hide().children().remove()
for(let cover=0; cover<=covers; cover++) {
const buttonText = cover==0 ? lang('cover_zero') : lang('selected_cover', cover.toString())
loadTemplate('#posButtonTemplate')
.find('a')
.first()
.addClass('coverSelectorButton')
.text(buttonText)
.data('cover', cover)
.appendTo(coverSelector)
}
}
$(() => {
OrderScreen.table = $('#pageContainer').data('table') || null
ajax('/orderScreen/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null)
})

View File

@@ -8,10 +8,11 @@ interface order {
} }
interface orderItem { interface orderItem {
id: number, id: number
qty: number, qty: number
print_group: print_group print_group: print_group
item: item item: item
cover: number
} }
interface print_group { interface print_group {
@@ -32,7 +33,7 @@ interface ApplicationState {
languageVars: Record<any, string> languageVars: Record<any, string>
} }
interface table { interface floorplan_table {
table_number: number, table_number: number,
room_id: number room_id: number
venue_id: number venue_id: number
@@ -71,11 +72,11 @@ interface room {
interface reservation { interface reservation {
id: number, id: number,
reservation_name: string, name: string,
reservation_time: number, time: number,
reservation_covers: number, covers: number,
reservation_created_at: number, created_at: number,
reservation_table_id: number, floorplan_table_id: number,
} }
interface keyboard { interface keyboard {

View File

@@ -120,108 +120,120 @@
::-webkit-scrollbar ::-webkit-scrollbar
display: none display: none
.pageGroup .pageGroup
/*display: inline-flex*/ /*display: inline-flex*/
@include flex-column-item @include flex-column-item
flex-basis: 100% flex-basis: 100%
flex-grow: 0 flex-grow: 0
overflow-x: auto overflow-x: auto
display: none display: none
.gridPage .gridPage
width: 100% width: 100%
height: 100% height: 100%
flex-shrink: 0 flex-shrink: 0
flex-grow: 0 flex-grow: 0
display: grid display: grid
grid-template-columns: repeat(6, 1fr)
grid-template-rows: repeat(8, 1fr)
.doubleWidth .doubleWidth
width: calc(200%) width: calc(200%)
z-index: 10 z-index: 10
.doubleHeight .doubleHeight
height: calc(200%) height: calc(200%)
z-index: 10 z-index: 10
.hasImage .hasImage
.buttonImg .buttonImg
background-repeat: no-repeat background-repeat: no-repeat
background-size: contain background-size: contain
background-position: center background-position: center
background-origin: content-box background-origin: content-box
.hasImage.normal .hasImage.normal
font-size: 0.8em font-size: 0.8em
.buttonImg .buttonImg
flex-basis: 40% flex-basis: 40%
height: 100% height: 100%
padding: 0.7em padding: 0.7em
justify-content: flex-end justify-content: flex-end
.text .text
@include flex
justify-content: flex-start
flex-basis: 60%
height: 100%
.hasImage.doubleHeight
@include flex-column
.buttonImg
padding: 0.6em
flex-basis: 65%
width: 100%
flex-shrink: 0
flex-grow: 0
.text
@include flex
align-items: flex-start
flex-grow: 0
flex-shrink: 0
flex-basis: 35%
width: 100%
overflow: hidden
font-size: 0.9em
.hasImage.doubleWidth
flex-direction: row
.buttonImg
@include flex
flex-basis: 30%
height: 100%
padding-top: 2%
.text
@include flex
flex-basis: 70%
height: 100%
justify-content: flex-start
.hasImage.doubleHeight.doubleWidth
flex-direction: row
.buttonImg
@include flex
flex-basis: 50%
height: 100%
.text
@include flex
flex-basis: 50%
height: 100%
.pageNavigation
@include flex @include flex
@include flex-column-item justify-content: flex-start
display: none flex-basis: 60%
height: 100%
> * .hasImage.doubleHeight
@include flex-item @include flex-column
.buttonImg
padding: 0.6em
flex-basis: 65%
width: 100%
flex-shrink: 0
flex-grow: 0
.text
@include flex
align-items: flex-start
flex-grow: 0
flex-shrink: 0
flex-basis: 35%
width: 100%
overflow: hidden
font-size: 0.9em
.hasImage.doubleWidth
flex-direction: row
.buttonImg
@include flex
flex-basis: 30%
height: 100%
padding-top: 2%
.text
@include flex
flex-basis: 70%
height: 100%
justify-content: flex-start
.hasImage.doubleHeight.doubleWidth
flex-direction: row
.buttonImg
@include flex
flex-basis: 50%
height: 100%
.text
@include flex
flex-basis: 50%
height: 100%
.pageNavigation
@include flex
@include flex-column-item
> *
@include flex-item
.coverSelector
display: flex
flex-wrap: wrap
border: 2px solid var(--global-border-color)
background: var(--global-bgcolor)
position: absolute
z-index: 100
.coverSelectorButton
flex-basis: 50%
.coverSelectorButton:first-of-type
flex-basis: 100%
.orderBoxTable .orderBoxTable
@@ -267,12 +279,65 @@
td.itemCell td.itemCell
text-align: left text-align: left
display: flex
flex-direction: column
tr.instructionRow tr.instructionRow
td td
font-weight: 100 font-weight: 100
td.itemCell td.itemCell
padding-left: 2em padding-left: 2em
small
font-size: 0
.qtyCell, .printGroupCell .qtyCell, .printGroupCell
font-size: 0 font-size: 0
.gridContainer
background: var(--global-bgcolor)
border: var(--global-border-color) solid 2px
z-index: 500
margin: auto
position: absolute
left: 0
right: 0
top: 50%
transform: translateY(-50%)
.gridContainerHeader
height: 3em
width: 100%
@include flex
background-color: var(--global-secondary-bgcolor)
border-bottom: solid 1px var(--global-border-color)
> *
@include flex
height: 100%
span
flex-basis: 90%
.closeGrid
flex-basis: 10%
.gridContainerGrid
width: 100%
@include flex-column
scrollbar-width: none
-ms-overflow-style: none
::-webkit-scrollbar
display: none
.pageGroup
display: inline-flex
flex-basis: 100%
flex-grow: 0
overflow-x: auto
.gridPage
width: 100%
height: 100%
flex-shrink: 0
flex-grow: 0
display: grid

View File

@@ -8,11 +8,11 @@
</head> </head>
<body> <body>
<div id="pageContainer"> <div id="pageContainer" <!--[var: containerAttributes]-->>
<div id="leftColumn"> <div id="leftColumn">
<h1 class="tableHeading"><!--[var: orderNumber]--></h1> <h1 class="tableHeading"><!--[var: orderNumber]--></h1>
<div class="tableInfo"> <div class="tableInfo">
<!--[var: coverSelectorButton]--> <!--[var: changeCoverNumberButton]-->
<a class="posButton">Logged in as <!--[arr:clerk|clerk_name]--></a> <a class="posButton">Logged in as <!--[arr:clerk|clerk_name]--></a>
</div> </div>
<div class="orderBox"> <div class="orderBox">
@@ -47,7 +47,7 @@
</div> </div>
<div class="functionColumn"> <div class="functionColumn">
<a class="posButton accumulateButton" data-active-in-mode="accumulate"><!--[lang:accumulate_function]--></a> <a class="posButton accumulateButton" data-active-in-mode="accumulate"><!--[lang:accumulate_function]--></a>
<a class="selectCoversButton posButton"><!--[lang:select_covers]--></a> <a class="showCoverSelectorButton posButton"><!--[lang:select_covers]--></a>
</div> </div>
<div class="functionColumn"> <div class="functionColumn">
<a class="posButton voidButton" data-active-in-mode="void"><!--[lang:void]--></a> <a class="posButton voidButton" data-active-in-mode="void"><!--[lang:void]--></a>
@@ -75,6 +75,10 @@
</div> </div>
<!--[template:keyboards]--> <!--[template:keyboards]-->
<!--[template:orderScreen/grid_container]-->
<!--[template:orderScreen/cover_selector]-->
<template id="posButtonTemplate">
<!--[template:components/posButton]-->
</template>
</body> </body>
</html> </html>

View File

@@ -0,0 +1 @@
<a href="#" class="posButton changeCoverNumberButton"><!--[var:covers]--></a>

View File

@@ -0,0 +1,3 @@
<div class="coverSelector">
<!--[var:coverSelectorButtons]-->
</div>

View File

@@ -1 +0,0 @@
<a href="#" class="posButton coverSelector"><!--[var:covers]--></a>

View File

@@ -0,0 +1,13 @@
<div class="gridContainer">
<div class="gridContainerHeader">
<span></span>
<div class="posButton closeGrid">×</div>
</div>
<div class="gridContainerGrid">
<div class="pageGroup"></div>
</div>
<div class="pageNavigation">
<a class="posButton prevButton"><!--[lang:prev_page]--></a>
<a class="posButton nextButton"><!--[lang:next_page]--></a>
</div>
</div>

View File

@@ -1,3 +1,6 @@
<div class="gridPage"> <div class="gridPage" style="
grid-template-columns: repeat(<!--[var:cols]-->, 1fr);
grid-template-rows: repeat(<!--[var:rows]-->, 1fr);
">
<!--[var:pageButtons]--> <!--[var:pageButtons]-->
</div> </div>