@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
open DredgeFramework
|
open DredgeFramework
|
||||||
open DredgePos
|
open DredgePos
|
||||||
|
open DredgePos.Types
|
||||||
open Floorplan
|
open Floorplan
|
||||||
open Microsoft.AspNetCore.Http
|
open Microsoft.AspNetCore.Http
|
||||||
open Reservations
|
open Reservations
|
||||||
@@ -41,22 +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) =
|
||||||
let pages = Entity.getAllInVenue<order_screen_page_group>
|
|
||||||
{|
|
{|
|
||||||
order_screen_pages = pages
|
order_screen_pages = Entity.GetAllInVenue<order_screen_page_group>
|
||||||
|
sales_categories = Entity.GetAllInVenue<sales_category>
|
||||||
|
print_groups = Entity.GetAllInVenue<print_group>
|
||||||
|
custom_item = Entity.GetAllByColumn<item> "item_code" "OPEN000" |> first
|
||||||
|
table = getTable tableNumber
|
||||||
|}
|
|}
|
||||||
|> ajaxSuccess
|
|> ajaxSuccess
|
||||||
|> json
|
|> json
|
||||||
@@ -70,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
|
||||||
|
|
||||||
@@ -110,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
|
||||||
@@ -146,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
|
||||||
@@ -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 =
|
||||||
|
|||||||
@@ -38,8 +38,10 @@ let GetFileName (file: string) = Path.GetFileName file
|
|||||||
|
|
||||||
let length (variable: 'T[]) = variable.Length
|
let length (variable: 'T[]) = variable.Length
|
||||||
let first (array: 'a[]) = array[0]
|
let first (array: 'a[]) = array[0]
|
||||||
|
|
||||||
let last (array: 'a[]) = array[array.Length-1]
|
let last (array: 'a[]) = array[array.Length-1]
|
||||||
|
|
||||||
|
let filterFirst (array:'a[]) = if array.Length > 0 then [|array[0]|] else [||]
|
||||||
|
|
||||||
let removeFalseValues (variable: bool[]) = variable |> Array.filter id
|
let removeFalseValues (variable: bool[]) = variable |> Array.filter id
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<Compile Include="Reservations.module.fs" />
|
<Compile Include="Reservations.module.fs" />
|
||||||
<Compile Include="Floorplan.module.fs" />
|
<Compile Include="Floorplan.module.fs" />
|
||||||
<Compile Include="Printer.module.fs" />
|
<Compile Include="Printer.module.fs" />
|
||||||
|
<Compile Include="Orders.module.fs" />
|
||||||
<Compile Include="OrderScreen.module.fs" />
|
<Compile Include="OrderScreen.module.fs" />
|
||||||
<Compile Include="Decorations.module.fs" />
|
<Compile Include="Decorations.module.fs" />
|
||||||
<Compile Include="Clerk.module.fs" />
|
<Compile Include="Clerk.module.fs" />
|
||||||
@@ -60,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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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,46 +19,58 @@ 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
|
||||||
where (eq "id" id)
|
where (eq "id" 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>
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ let get var =
|
|||||||
else
|
else
|
||||||
"Missing language variable: " + var
|
"Missing language variable: " + var
|
||||||
|
|
||||||
let getAndReplace languageVar replacements =
|
let getAndReplace languageVar (replacements: 'x list) =
|
||||||
let langString = get languageVar
|
let langString = get languageVar
|
||||||
replacements
|
replacements
|
||||||
|> List.mapi (fun index string
|
|> List.mapi (fun index replacement
|
||||||
-> index + 1, string)
|
-> index + 1, replacement.ToString())
|
||||||
|> List.fold (fun (result: string) (index, string)
|
|> List.fold (fun (result: string) (index, string)
|
||||||
-> result.Replace($"[{index}]", string)
|
-> result.Replace($"[{index}]", string)
|
||||||
) langString
|
) langString
|
||||||
@@ -1,34 +1,27 @@
|
|||||||
module OrderScreen
|
module OrderScreen
|
||||||
open System.Security.Cryptography.Xml
|
|
||||||
open DredgeFramework
|
open DredgeFramework
|
||||||
open DredgePos
|
open DredgePos
|
||||||
|
open DredgePos.Types
|
||||||
open FSharp.Collections
|
open FSharp.Collections
|
||||||
open Thoth.Json.Net
|
open Thoth.Json.Net
|
||||||
open Types
|
|
||||||
open Theme
|
open Theme
|
||||||
|
|
||||||
let htmlAttributes (attributes: Map<string, string>) =
|
|
||||||
" " + (attributes
|
|
||||||
|> Map.toArray
|
|
||||||
|> Array.map (fun (attribute, value) -> attribute+"="+value)
|
|
||||||
|> String.concat " ")
|
|
||||||
|
|
||||||
|
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 =
|
||||||
map [
|
map [
|
||||||
"data-item-code", item.item_code
|
"data-item", jsonEncode item
|
||||||
"data-item-price", item.price1.ToString()
|
|
||||||
"data-item-name", item.item_name
|
|
||||||
"data-item-type", item.item_type
|
|
||||||
"data-item-category", item.item_category.ToString()
|
|
||||||
] |> htmlAttributes
|
] |> htmlAttributes
|
||||||
|
|
||||||
{|
|
{|
|
||||||
@@ -36,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
|
||||||
@@ -50,55 +65,73 @@ let renderButton (buttonId: int) =
|
|||||||
then "invisible"
|
then "invisible"
|
||||||
else ""
|
else ""
|
||||||
|
|
||||||
let image = if button.image.Length > 0
|
let image = if button.image.Length > 0 then loadTemplateWithVars "orderScreen/button_image" (map ["image", button.image]) else ""
|
||||||
then loadTemplateWithVars "orderScreen/button_image" (map ["image", button.image])
|
|
||||||
else ""
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
let printGroupPosButton (printGroup: print_group) =
|
||||||
|
PosButton (language.getAndReplace "print_with" [printGroup.name]) "printGroupOverrideButton toggle" $"""data-value="{printGroup.id}" """
|
||||||
|
|
||||||
|
let generateSalesCategoryOverrideButtons () =
|
||||||
|
Entity.GetAllInVenue<print_group>
|
||||||
|
|> Array.map printGroupPosButton
|
||||||
|
|> Array.append [|PosButton (language.getAndReplace "print_with" ["default"]) "printGroupOverrideButton toggle default active" """data-value="0" """|]
|
||||||
|
|> 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
|
|
||||||
3
Orders.module.fs
Normal file
3
Orders.module.fs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module Orders
|
||||||
|
|
||||||
|
let getHighestOrderNumber () = 6
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
open System
|
open System
|
||||||
open DredgePos.Types
|
open DredgePos.Types
|
||||||
|
open FSharp.Data
|
||||||
open Microsoft.AspNetCore.Http
|
open Microsoft.AspNetCore.Http
|
||||||
open Floorplan
|
open Floorplan
|
||||||
open Giraffe
|
open Giraffe
|
||||||
@@ -19,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"
|
||||||
|
|
||||||
@@ -36,12 +37,28 @@ let loadFloorplan (ctx: HttpContext) : HttpHandler =
|
|||||||
|
|
||||||
htmlString <| Theme.loadTemplateWithVarsArraysScriptsAndStyles "floorplan" variables arrays scripts styles
|
htmlString <| Theme.loadTemplateWithVarsArraysScriptsAndStyles "floorplan" variables arrays scripts styles
|
||||||
|
|
||||||
let loadOrderScreen (ctx: HttpContext) : HttpHandler =
|
let loadOrderScreen (ctx: HttpContext) (tableNumber: int) : HttpHandler =
|
||||||
Session.RequireClerkAuthentication ctx
|
Session.RequireClerkAuthentication ctx
|
||||||
|
|
||||||
|
let covers = if tableNumber > 0 then (getTable tableNumber).default_covers else 0
|
||||||
|
let coverString = language.getAndReplace "covers" [covers]
|
||||||
|
|
||||||
|
let changeCoverNumberButton = if tableNumber > 0 then Theme.loadTemplateWithVars "orderScreen/change_cover_number_button" (map ["covers", coverString]) else ""
|
||||||
|
|
||||||
|
let orderNumber =
|
||||||
|
if tableNumber > 0 then language.getAndReplace "active_table" [tableNumber]
|
||||||
|
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.getAll<order_screen_page_group>
|
Entity.GetAllInVenue<order_screen_page_group>
|
||||||
|> Array.filter (fun category -> category.id <> 0)
|
|> Array.filter (fun page_group -> page_group.id <> 0)
|
||||||
|
|> Array.sortBy (fun {order=order} -> order)
|
||||||
|> Array.map (fun category ->
|
|> Array.map (fun category ->
|
||||||
let categoryMap = recordToMap category
|
let categoryMap = recordToMap category
|
||||||
let categoryArray = map ["page", categoryMap]
|
let categoryArray = map ["page", categoryMap]
|
||||||
@@ -54,19 +71,33 @@ let loadOrderScreen (ctx: HttpContext) : HttpHandler =
|
|||||||
|> Array.map OrderScreen.getPagesHTML
|
|> Array.map OrderScreen.getPagesHTML
|
||||||
|> String.concat "\n"
|
|> String.concat "\n"
|
||||||
|
|
||||||
|
let coverSelectorButtons =
|
||||||
|
Array.init (covers+1) id
|
||||||
|
|> Array.map(fun coverNumber ->
|
||||||
|
let text = if coverNumber > 0 then language.getAndReplace "selected_cover" [coverNumber]
|
||||||
|
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
|
||||||
|
"changeCoverNumberButton", changeCoverNumberButton
|
||||||
|
"covers", coverString
|
||||||
|
"salesCategoryOverrideButtons", OrderScreen.generateSalesCategoryOverrideButtons ()
|
||||||
|
"coverSelectorButtons", coverSelectorButtons
|
||||||
]
|
]
|
||||||
|
|
||||||
let styles = ["dredgepos.orderScreen.css"]
|
let styles = ["dredgepos.orderScreen.css"]
|
||||||
let scripts = ["dredgepos.orderScreen.js"]
|
let scripts = ["dredgepos.tables.js";"../external/currency.min.js";"dredgepos.orderScreen.js"; ]
|
||||||
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()
|
||||||
|
|||||||
@@ -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 {
|
||||||
@@ -52,7 +54,8 @@ module Program =
|
|||||||
get "/" (redirectTo true "/login")
|
get "/" (redirectTo true "/login")
|
||||||
get "/login" (warbler (fun _ -> PageController.loadHomePage() ))
|
get "/login" (warbler (fun _ -> PageController.loadHomePage() ))
|
||||||
get "/floorplan" (warbler (fun ctx -> PageController.loadFloorplan (snd ctx)))
|
get "/floorplan" (warbler (fun ctx -> PageController.loadFloorplan (snd ctx)))
|
||||||
get "/order" (warbler (fun ctx -> PageController.loadOrderScreen (snd ctx)))
|
get "/order" (warbler (fun ctx -> PageController.loadOrderScreen (snd ctx) 0))
|
||||||
|
getf "/order/%i" (fun number -> (warbler (fun ctx -> PageController.loadOrderScreen (snd ctx) number)))
|
||||||
forward "/ajax" floorplanRouter
|
forward "/ajax" floorplanRouter
|
||||||
forward "/orderScreen" orderScreenRouter
|
forward "/orderScreen" orderScreenRouter
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module Theme
|
module Theme
|
||||||
|
|
||||||
open System
|
open System.Web
|
||||||
open System.IO
|
open System.IO
|
||||||
open System.Collections.Generic
|
open System.Collections.Generic
|
||||||
open System.Text.RegularExpressions
|
open System.Text.RegularExpressions
|
||||||
@@ -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) =
|
||||||
@@ -78,7 +78,7 @@ let ParseSimpleLanguageVariables (string:string) =
|
|||||||
|
|
||||||
let ParseLanguageVariablesWithReplacements (string: string) =
|
let ParseLanguageVariablesWithReplacements (string: string) =
|
||||||
Regex.Replace(string, "<!--\[lang\:(.*?)\|(.*?)\]-->",
|
Regex.Replace(string, "<!--\[lang\:(.*?)\|(.*?)\]-->",
|
||||||
new MatchEvaluator(
|
MatchEvaluator(
|
||||||
fun matchedVar ->
|
fun matchedVar ->
|
||||||
let varName = matchedVar.Groups[1].ToString()
|
let varName = matchedVar.Groups[1].ToString()
|
||||||
let replacements = matchedVar.Groups[2].ToString()
|
let replacements = matchedVar.Groups[2].ToString()
|
||||||
@@ -137,4 +137,19 @@ let loadTemplateWithVarsAndScripts templateName vars scripts =
|
|||||||
let loadTemplateWithVarsAndStyles = loadTemplateWithVarsAndScripts
|
let loadTemplateWithVarsAndStyles = loadTemplateWithVarsAndScripts
|
||||||
|
|
||||||
let loadTemplateWithVarsScriptsAndStyles templateName vars scripts styles =
|
let loadTemplateWithVarsScriptsAndStyles templateName vars scripts styles =
|
||||||
loadTemplateWithVarsArraysScriptsAndStyles templateName vars Map.empty<string, Map<string, string>> scripts styles
|
loadTemplateWithVarsArraysScriptsAndStyles templateName vars Map.empty<string, Map<string, string>> scripts styles
|
||||||
|
|
||||||
|
|
||||||
|
let htmlAttributes (attributes: Map<string, string>) =
|
||||||
|
" " + (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
|
||||||
47
Types.fs
47
Types.fs
@@ -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>]
|
||||||
@@ -29,11 +35,20 @@ type floorplan_table = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type category = {
|
type print_group = {
|
||||||
id: int
|
id: int
|
||||||
category_name: string
|
name: string
|
||||||
category_print_group: string
|
printer: int
|
||||||
category_department: string
|
venue_id: int
|
||||||
|
}
|
||||||
|
|
||||||
|
[<CLIMutable>]
|
||||||
|
type sales_category = {
|
||||||
|
id: int
|
||||||
|
parent: int
|
||||||
|
name: string
|
||||||
|
print_group: int
|
||||||
|
venue_id: int
|
||||||
}
|
}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
@@ -64,7 +79,7 @@ type clerk = {id: int; clerk_name: string; clerk_login_code: int; clerk_usergrou
|
|||||||
type session = {id: int; session_id: string; clerk_json: string; clerk_id: int; expires: int}
|
type session = {id: int; session_id: string; clerk_json: string; clerk_id: int; expires: int}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type order_screen_page_group = {id: int; venue_id: int; label: string; grid_id: int}
|
type order_screen_page_group = {id: int; order: int; venue_id: int; label: string; grid_id: int}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type grid = {id: int; grid_name: string; grid_rows: int; grid_cols: int; grid_data: string}
|
type grid = {id: int; grid_name: string; grid_rows: int; grid_cols: int; grid_data: string}
|
||||||
@@ -89,9 +104,9 @@ type item = {
|
|||||||
item_category: int
|
item_category: int
|
||||||
item_name: string
|
item_name: string
|
||||||
item_type: string
|
item_type: string
|
||||||
price1: float
|
price1: int
|
||||||
price2: float
|
price2: int
|
||||||
price3: float
|
price3: int
|
||||||
price4: float
|
price4: int
|
||||||
price5: float
|
price5: int
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,12 @@
|
|||||||
"functions_header":"Functions",
|
"functions_header":"Functions",
|
||||||
"close_order_function":"Close Without Saving",
|
"close_order_function":"Close Without Saving",
|
||||||
"accumulate_function":"Accumulate Items",
|
"accumulate_function":"Accumulate Items",
|
||||||
|
"multiplier":"Enter a Number",
|
||||||
"void":"Void",
|
"void":"Void",
|
||||||
"pay_function":"Pay",
|
"pay_function":"Pay",
|
||||||
"print_function":"Save & Print",
|
"print_function":"Save & Print",
|
||||||
"freetext_button":"Keyboard",
|
"freetext_button":"Custom Instruction",
|
||||||
|
"custom_item_button":"Custom Item",
|
||||||
"numpad_button":"Numpad",
|
"numpad_button":"Numpad",
|
||||||
"select_covers":"Cover #",
|
"select_covers":"Cover #",
|
||||||
"how_many_covers":"How many people are on this table?",
|
"how_many_covers":"How many people are on this table?",
|
||||||
@@ -51,6 +53,8 @@
|
|||||||
"merge_table":"Merge Table",
|
"merge_table":"Merge Table",
|
||||||
"unmerge_table":"Unmerge Table",
|
"unmerge_table":"Unmerge Table",
|
||||||
"order_table":"Place Order",
|
"order_table":"Place Order",
|
||||||
|
"order_number": "Order [1]",
|
||||||
|
"new_order": "New Order",
|
||||||
"view_table":"View Table",
|
"view_table":"View Table",
|
||||||
"reserve_table":"Reserve Table",
|
"reserve_table":"Reserve Table",
|
||||||
"unreserve_table":"Delete Reservation",
|
"unreserve_table":"Delete Reservation",
|
||||||
@@ -85,5 +89,9 @@
|
|||||||
"partial_table":"Partial Table",
|
"partial_table":"Partial Table",
|
||||||
"paying_table":"Paying Table [1]",
|
"paying_table":"Paying Table [1]",
|
||||||
"msgbox_amount_select":"Enter Amount",
|
"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.",
|
||||||
|
"enter_item_name": "Enter Item Name",
|
||||||
|
"enter_item_price": "Enter Item Price"
|
||||||
}
|
}
|
||||||
12
wwwroot/scripts/external/currency.min.js
vendored
Normal file
12
wwwroot/scripts/external/currency.min.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
currency.js - v2.0.4
|
||||||
|
http://scurker.github.io/currency.js
|
||||||
|
|
||||||
|
Copyright (c) 2021 Jason Wilson
|
||||||
|
Released under MIT license
|
||||||
|
*/
|
||||||
|
(function(e,g){"object"===typeof exports&&"undefined"!==typeof module?module.exports=g():"function"===typeof define&&define.amd?define(g):(e=e||self,e.currency=g())})(this,function(){function e(b,a){if(!(this instanceof e))return new e(b,a);a=Object.assign({},m,a);var d=Math.pow(10,a.precision);this.intValue=b=g(b,a);this.value=b/d;a.increment=a.increment||1/d;a.groups=a.useVedic?n:p;this.s=a;this.p=d}function g(b,a){var d=2<arguments.length&&void 0!==arguments[2]?arguments[2]:!0;var c=a.decimal;
|
||||||
|
var h=a.errorOnInvalid,k=a.fromCents,l=Math.pow(10,a.precision),f=b instanceof e;if(f&&k)return b.intValue;if("number"===typeof b||f)c=f?b.value:b;else if("string"===typeof b)h=new RegExp("[^-\\d"+c+"]","g"),c=new RegExp("\\"+c,"g"),c=(c=b.replace(/\((.*)\)/,"-$1").replace(h,"").replace(c,"."))||0;else{if(h)throw Error("Invalid Input");c=0}k||(c=(c*l).toFixed(4));return d?Math.round(c):c}var m={symbol:"$",separator:",",decimal:".",errorOnInvalid:!1,precision:2,pattern:"!#",negativePattern:"-!#",format:function(b,
|
||||||
|
a){var d=a.pattern,c=a.negativePattern,h=a.symbol,k=a.separator,l=a.decimal;a=a.groups;var f=(""+b).replace(/^-/,"").split("."),q=f[0];f=f[1];return(0<=b.value?d:c).replace("!",h).replace("#",q.replace(a,"$1"+k)+(f?l+f:""))},fromCents:!1},p=/(\d)(?=(\d{3})+\b)/g,n=/(\d)(?=(\d\d)+\d\b)/g;e.prototype={add:function(b){var a=this.s,d=this.p;return e((this.intValue+g(b,a))/(a.fromCents?1:d),a)},subtract:function(b){var a=this.s,d=this.p;return e((this.intValue-g(b,a))/(a.fromCents?1:d),a)},multiply:function(b){var a=
|
||||||
|
this.s;return e(this.intValue*b/(a.fromCents?1:Math.pow(10,a.precision)),a)},divide:function(b){var a=this.s;return e(this.intValue/g(b,a,!1),a)},distribute:function(b){var a=this.intValue,d=this.p,c=this.s,h=[],k=Math[0<=a?"floor":"ceil"](a/b),l=Math.abs(a-k*b);for(d=c.fromCents?1:d;0!==b;b--){var f=e(k/d,c);0<l--&&(f=f[0<=a?"add":"subtract"](1/d));h.push(f)}return h},dollars:function(){return~~this.value},cents:function(){return~~(this.intValue%this.p)},format:function(b){var a=this.s;return"function"===
|
||||||
|
typeof b?b(this,a):a.format(this,Object.assign({},a,b))},toString:function(){var b=this.s,a=b.increment;return(Math.round(this.intValue/this.p/a)*a).toFixed(b.precision)},toJSON:function(){return this.value}};return e});
|
||||||
@@ -1,186 +1,239 @@
|
|||||||
let Application : ApplicationState = {
|
/// <reference path="./typings/currency.d.ts" />
|
||||||
keyboard : null,
|
|
||||||
mode: [],
|
const Application: ApplicationState = {
|
||||||
languageVars: {}
|
keyboard: null,
|
||||||
}
|
mode: [],
|
||||||
|
languageVars: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Parses a language variable. */
|
/** Parses a language variable. */
|
||||||
let lang = (key: string, replacements?: string[] | string) => {
|
const lang = (key: string, replacements?: string[] | string) => {
|
||||||
let finalValue = Application.languageVars[key] || ''
|
let finalValue = Application.languageVars[key] || ''
|
||||||
|
|
||||||
if(!replacements) return finalValue
|
if (!replacements) return finalValue
|
||||||
if(typeof replacements === 'string') replacements = [replacements]
|
if (typeof replacements === 'string') replacements = [replacements]
|
||||||
|
|
||||||
replacements.forEach( (replacement, index) => {
|
replacements.forEach((replacement, index) => {
|
||||||
let correctIndex = index+1
|
const correctIndex = index + 1
|
||||||
finalValue = finalValue.replace(`[${correctIndex}]`, replacement)
|
finalValue = finalValue.replace(`[${correctIndex}]`, replacement)
|
||||||
})
|
})
|
||||||
|
|
||||||
return finalValue
|
return finalValue
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check if a variable is defined */
|
/** Check if a variable is defined */
|
||||||
let defined = (variable: any) => {
|
const defined = (variable: any) => {
|
||||||
return typeof variable !== 'undefined'
|
return typeof variable !== 'undefined'
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Call an Ajax function asynchronously */
|
/** Call an Ajax function asynchronously */
|
||||||
let ajax = (endpoint : string, data: any, method = 'POST', successFunction : Function , errorFunction : Function, beforeFunction: any) => {
|
const ajax = (endpoint: string, data: any, method = 'POST', successFunction: Function, errorFunction: Function, beforeFunction: any) => {
|
||||||
data = (data == null) ? data : JSON.stringify(data)
|
data = (data == null) ? data : JSON.stringify(data)
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
|
url: endpoint,
|
||||||
|
method: method,
|
||||||
|
data: data,
|
||||||
|
success: (response: ajaxResult) => {
|
||||||
|
if (successFunction && response.status == 'success')
|
||||||
|
successFunction(JSON.parse(response.data))
|
||||||
|
else if (errorFunction && response.status != 'success') {
|
||||||
|
errorFunction(JSON.parse(response.data))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: (error) => console.log(error.statusCode),
|
||||||
|
beforeSend: beforeFunction
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
For the flow of the app, synchronous is commonly preferred
|
||||||
|
though trying to keep its usage as low as possible.
|
||||||
|
*/
|
||||||
|
const ajaxSync = (endpoint: string, data?: any, method = 'POST') => {
|
||||||
|
const response = JSON.parse(
|
||||||
|
$.ajax({
|
||||||
url: endpoint,
|
url: endpoint,
|
||||||
method: method,
|
method: method,
|
||||||
data: data,
|
data: JSON.stringify(data),
|
||||||
success: (response: ajaxResult) => {
|
async: false,
|
||||||
if(successFunction && response.status == 'success')
|
}).responseText)
|
||||||
successFunction(JSON.parse(response.data))
|
|
||||||
else if (errorFunction && response.status != 'success'){
|
if (response.data) {
|
||||||
errorFunction(JSON.parse(response.data))
|
response.data = JSON.parse(response.data)
|
||||||
}
|
return response.data
|
||||||
},
|
}
|
||||||
error: (error) => console.log(error.statusCode),
|
|
||||||
beforeSend: beforeFunction
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redirect to a specific URL */
|
||||||
|
const redirect = (url: string): void => location.assign(url)
|
||||||
|
|
||||||
|
const resize = () => {
|
||||||
|
$('#pageContainer').height(window.innerHeight + "px");
|
||||||
|
}
|
||||||
|
|
||||||
|
const setupCore = (languageVars: Record<string, string>) => {
|
||||||
|
Application.languageVars = languageVars
|
||||||
|
const doc = $(document)
|
||||||
|
doc.on('click', '#alertNo, #alertOk', hideAlerts)
|
||||||
|
doc.on('click', '.toggle', toggle)
|
||||||
|
window.addEventListener('resize', resize)
|
||||||
|
resize()
|
||||||
|
|
||||||
|
setElementVisibilityByMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const posAlert = (message: string, title = 'Message') => {
|
||||||
|
const alertBox = $('#alert')
|
||||||
|
alertBox.css('display', 'flex');
|
||||||
|
alertBox.data('value', '');
|
||||||
|
$('#alertHeading').text(title);
|
||||||
|
$('#alertMessage').text(message);
|
||||||
|
|
||||||
|
$('#alertOk').css('display', 'flex');
|
||||||
|
$('#alertYes').css('display', 'none');
|
||||||
|
$('#alertNo').css('display', 'none');
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmation = (message: string, data: any, title = 'Confirm', submitFunction = (data: any) => {hideAlerts()}) => {
|
||||||
|
const alert = $('#alert')
|
||||||
|
|
||||||
|
$(document).on('click', '#alert #alertYes', () => {
|
||||||
|
hideAlerts()
|
||||||
|
submitFunction(data)
|
||||||
|
$(document).off('click', '#alert #alertYes')
|
||||||
|
})
|
||||||
|
|
||||||
|
alert.css('display', 'flex')
|
||||||
|
$('#alertHeading').html(title)
|
||||||
|
$('#alertMessage').html(message)
|
||||||
|
|
||||||
|
$('#alertOk').css('display', 'none')
|
||||||
|
$('#alertYes').css('display', 'flex')
|
||||||
|
$('#alertNo').css('display', 'flex')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const hideAlerts = () => $('#alert').hide()
|
||||||
|
|
||||||
|
const turnOnMode = (mode: PosMode) => {
|
||||||
|
Application.mode.push(mode)
|
||||||
|
setElementVisibilityByMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
const turnOffMode = (mode: PosMode) => {
|
||||||
|
Application.mode = Application.mode.filter((value) => value != mode)
|
||||||
|
setElementVisibilityByMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleMode = (mode: PosMode) => {
|
||||||
|
if (!isInMode(mode))
|
||||||
|
turnOnMode(mode)
|
||||||
|
else
|
||||||
|
turnOffMode(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearModes = () => {
|
||||||
|
Application.mode = []
|
||||||
|
setElementVisibilityByMode()
|
||||||
|
}
|
||||||
|
|
||||||
|
const isInMode = (mode: PosMode) => Application.mode.includes(mode)
|
||||||
|
|
||||||
|
const setElementVisibilityByMode = () => {
|
||||||
|
const mode = Application.mode
|
||||||
|
const elements = $('[data-visible-in-mode]')
|
||||||
|
|
||||||
|
elements.each((index, elem) => {
|
||||||
|
const element = $(elem)
|
||||||
|
const visibleInModes: PosModes = element.data('visible-in-mode')
|
||||||
|
|
||||||
|
const showElement = visibleInModes.every(visibleMode => {
|
||||||
|
return mode.includes(visibleMode)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (element.hasClass('useVisibility')) {
|
||||||
|
if (showElement) {
|
||||||
|
element.css('visibility', 'visible')
|
||||||
|
} else element.css('visibility', 'hidden')
|
||||||
|
} else element.toggle(showElement)
|
||||||
|
})
|
||||||
|
|
||||||
|
const invisibleElements = $('[data-invisible-in-mode]')
|
||||||
|
invisibleElements.each((index, elem) => {
|
||||||
|
const element = $(elem)
|
||||||
|
const inVisibleInModes: PosModes = element.data('invisible-in-mode')
|
||||||
|
const hideElement = inVisibleInModes.some(invisibleMode => {
|
||||||
|
return mode.includes(invisibleMode)
|
||||||
})
|
})
|
||||||
|
element.toggle(!hideElement)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
$('[data-active-in-mode]').each((index, elem) => {
|
||||||
|
const button = $(elem)
|
||||||
|
const activeInMode: PosMode = button.data('active-in-mode')
|
||||||
|
|
||||||
|
mode.includes(activeInMode)
|
||||||
|
? button.addClass('active')
|
||||||
|
: button.removeClass('active')
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const pulseElement = (element: JQuery) => element.addClass('pulse').on('animationend', () => element.removeClass('pulse'))
|
||||||
|
|
||||||
|
Array.prototype.where = function<x>(this: x[], property: string, value: any) {
|
||||||
|
return this.filter( item => (item as any)[property] === value)[0] || null
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
while(true){
|
||||||
|
id++
|
||||||
|
yield id
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadTemplate = (templateSelector: string) => {
|
||||||
|
const content = $(templateSelector)
|
||||||
|
.clone()
|
||||||
|
.removeAttr('id')
|
||||||
|
.prop('content')
|
||||||
|
return $(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
$(() => ajax('/ajax/languageVars', null, 'GET', setupCore, null, null))
|
||||||
For the flow of the app, synchronous is commonly preferred
|
|
||||||
though trying to keep its usage as low as possible.
|
|
||||||
*/
|
|
||||||
let ajaxSync = (endpoint : string, data?: any, method = 'POST') => {
|
|
||||||
let response = JSON.parse(
|
|
||||||
$.ajax({
|
|
||||||
url: endpoint,
|
|
||||||
method: method,
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
async:false,
|
|
||||||
}).responseText)
|
|
||||||
|
|
||||||
if(response.data) {
|
|
||||||
response.data = JSON.parse(response.data)
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Redirect to a specific URL */
|
|
||||||
let redirect = (url: string) : void => location.assign(url)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const resize = () => {
|
|
||||||
$('#pageContainer').height(window.innerHeight + "px");
|
|
||||||
}
|
|
||||||
|
|
||||||
let setupCore = (languageVars: Record<string, string>) => {
|
|
||||||
Application.languageVars = languageVars
|
|
||||||
const doc = $(document)
|
|
||||||
doc.on('click', '#alertNo, #alertOk', hideAlerts)
|
|
||||||
window.addEventListener('resize', resize)
|
|
||||||
resize()
|
|
||||||
|
|
||||||
setElementVisibilityByMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
let posAlert = (message: string, title='Message') => {
|
|
||||||
let alertBox = $('#alert')
|
|
||||||
alertBox.css('display', 'flex');
|
|
||||||
alertBox.data('value', '');
|
|
||||||
$('#alertHeading').text(title);
|
|
||||||
$('#alertMessage').text(message);
|
|
||||||
|
|
||||||
$('#alertOk').css('display', 'flex');
|
|
||||||
$('#alertYes').css('display', 'none');
|
|
||||||
$('#alertNo').css('display', 'none');
|
|
||||||
}
|
|
||||||
|
|
||||||
let confirmation = (message: string, data: any, title='Confirm', submitFunction = (data: any) => {hideAlerts()}) => {
|
|
||||||
let alert = $('#alert')
|
|
||||||
|
|
||||||
$(document).on('click', '#alert #alertYes', () => {
|
|
||||||
hideAlerts()
|
|
||||||
submitFunction(data)
|
|
||||||
$(document).off('click', '#alert #alertYes')
|
|
||||||
})
|
|
||||||
|
|
||||||
alert.css('display', 'flex')
|
|
||||||
$('#alertHeading').html(title)
|
|
||||||
$('#alertMessage').html(message)
|
|
||||||
|
|
||||||
$('#alertOk').css('display', 'none')
|
|
||||||
$('#alertYes').css('display', 'flex')
|
|
||||||
$('#alertNo').css('display', 'flex')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let hideAlerts = () => $('#alert').hide()
|
|
||||||
|
|
||||||
let turnOnMode = (mode : PosMode) => {
|
|
||||||
Application.mode.push(mode)
|
|
||||||
setElementVisibilityByMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
let turnOffMode = (mode : PosMode) => {
|
|
||||||
Application.mode = Application.mode.filter((value) => value != mode)
|
|
||||||
setElementVisibilityByMode()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
let toggleMode = (mode: PosMode) => {
|
|
||||||
if(!isInMode(mode))
|
|
||||||
turnOnMode(mode)
|
|
||||||
else
|
|
||||||
turnOffMode(mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
let clearModes = () => {Application.mode = []}
|
|
||||||
let isInMode = (mode: PosMode) => Application.mode.includes(mode)
|
|
||||||
|
|
||||||
let setElementVisibilityByMode = () => {
|
|
||||||
const mode = Application.mode
|
|
||||||
const elements = $('[data-visible-in-mode]')
|
|
||||||
|
|
||||||
elements.each((index, elem) => {
|
|
||||||
let element = $(elem)
|
|
||||||
let visibleInModes : PosModes = element.data('visible-in-mode')
|
|
||||||
|
|
||||||
let showElement = visibleInModes.every( visibleMode => {
|
|
||||||
return mode.includes(visibleMode)
|
|
||||||
});
|
|
||||||
|
|
||||||
if(element.hasClass('useVisibility')){
|
|
||||||
if(showElement) {
|
|
||||||
element.css('visibility', 'visible')
|
|
||||||
} else element.css('visibility', 'hidden')
|
|
||||||
} else element.toggle(showElement)
|
|
||||||
})
|
|
||||||
|
|
||||||
const invisibleElements = $('[data-invisible-in-mode]')
|
|
||||||
invisibleElements.each((index, elem) => {
|
|
||||||
let element = $(elem)
|
|
||||||
let inVisibleInModes: PosModes = element.data('invisible-in-mode')
|
|
||||||
let hideElement = inVisibleInModes.some(invisibleMode => {
|
|
||||||
return mode.includes(invisibleMode)
|
|
||||||
})
|
|
||||||
element.toggle(!hideElement)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
$('[data-active-in-mode]').each((index, elem) =>{
|
|
||||||
const button = $(elem)
|
|
||||||
const activeInMode : PosMode = button.data('active-in-mode')
|
|
||||||
|
|
||||||
mode.includes(activeInMode)
|
|
||||||
? button.addClass('active')
|
|
||||||
: button.removeClass('active')
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$( () => ajax('/ajax/languageVars', null, 'GET', setupCore, null, null))
|
|
||||||
@@ -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[]
|
||||||
@@ -68,6 +68,11 @@ const setupFloorplanEvents = () => {
|
|||||||
doc.on('click', '.transferTableButton', toggleTransferMode)
|
doc.on('click', '.transferTableButton', toggleTransferMode)
|
||||||
doc.on('click', '.reserveTableButton', reserveTable)
|
doc.on('click', '.reserveTableButton', reserveTable)
|
||||||
doc.on('click', '.unreserveTableButton', unreserveTable)
|
doc.on('click', '.unreserveTableButton', unreserveTable)
|
||||||
|
doc.on('click', '.placeOrderButton', placeOrderButtonClicked)
|
||||||
|
}
|
||||||
|
|
||||||
|
const placeOrderButtonClicked = () => {
|
||||||
|
redirect(`/order/${Floorplan.selectedTableNumber}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const roomButtonClicked = (e: Event) => {
|
const roomButtonClicked = (e: Event) => {
|
||||||
@@ -132,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({
|
||||||
@@ -216,6 +221,8 @@ const setupTableEvents = (tableGroup: Konva.Group) => {
|
|||||||
|
|
||||||
tableGroup.on('click', tableClicked)
|
tableGroup.on('click', tableClicked)
|
||||||
tableGroup.on('tap', tableClicked)
|
tableGroup.on('tap', tableClicked)
|
||||||
|
tableGroup.on('dbltap', tableDblClicked)
|
||||||
|
tableGroup.on('dblclick', tableDblClicked)
|
||||||
tableGroup.on('dragend', tableGroupTransformed)
|
tableGroup.on('dragend', tableGroupTransformed)
|
||||||
tableShape.on('transformend', tableShapeTransformed)
|
tableShape.on('transformend', tableShapeTransformed)
|
||||||
}
|
}
|
||||||
@@ -236,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,
|
||||||
@@ -258,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
|
||||||
@@ -302,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 {
|
||||||
@@ -333,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 )
|
||||||
@@ -347,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())
|
||||||
@@ -357,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,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)
|
||||||
}
|
}
|
||||||
@@ -382,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)
|
||||||
}
|
}
|
||||||
@@ -431,9 +438,16 @@ 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 tableClicked = (event: Konva.KonvaEventObject<any>) => {
|
const tableDblClicked = (event: Konva.KonvaEventObject<any>) => {
|
||||||
|
let tableShape = getTableShapeFromGroup(event.currentTarget as Konva.Group)
|
||||||
|
const table = getTableDataFromShape(tableShape)
|
||||||
|
redirect(`/order/${table.table_number}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const tableClicked = (event: Konva.KonvaEventObject<any>) => {
|
||||||
let tableShape = getTableShapeFromGroup(event.currentTarget as Konva.Group)
|
let tableShape = getTableShapeFromGroup(event.currentTarget as Konva.Group)
|
||||||
const table = getTableDataFromShape(tableShape)
|
const table = getTableDataFromShape(tableShape)
|
||||||
|
|
||||||
@@ -704,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,
|
||||||
@@ -724,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)
|
||||||
@@ -752,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()
|
||||||
@@ -762,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'))
|
||||||
@@ -771,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'])
|
||||||
@@ -783,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']
|
||||||
|
|
||||||
@@ -795,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
|
||||||
@@ -804,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']
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,54 @@
|
|||||||
interface OrderScreen{
|
type OrderScreenData = {
|
||||||
order_screen_pages: order_screen_page[]
|
order_screen_pages: order_screen_page[]
|
||||||
|
sales_categories: sales_category[]
|
||||||
|
print_groups: print_group[]
|
||||||
|
custom_item: item
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
custom_item: item,
|
||||||
|
selected_cover: number
|
||||||
|
table: floorplan_table,
|
||||||
}
|
}
|
||||||
|
|
||||||
let OrderScreen : OrderScreen = {
|
let OrderScreen : OrderScreen = {
|
||||||
order_screen_pages: null
|
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,
|
||||||
|
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')
|
||||||
|
|
||||||
activeGrid.find('.gridPage').length > 1
|
activeGrid.find('.gridPage').length > 1
|
||||||
? navButtons.show()
|
? navButtons.show()
|
||||||
@@ -22,26 +57,548 @@ const loadPageGroup = (e: Event) => {
|
|||||||
activeGrid.css('display', 'inline-flex')
|
activeGrid.css('display', 'inline-flex')
|
||||||
}
|
}
|
||||||
|
|
||||||
const setupOrderScreen = (data: OrderScreen) => {
|
const setupOrderScreen = (data: OrderScreenData) => {
|
||||||
OrderScreen = data
|
|
||||||
|
$('.coverSelector, .gridContainer').hide()
|
||||||
|
|
||||||
|
OrderScreen.order_screen_pages = data.order_screen_pages
|
||||||
|
OrderScreen.sales_categories = data.sales_categories
|
||||||
|
OrderScreen.print_groups = data.print_groups
|
||||||
|
OrderScreen.custom_item = data.custom_item
|
||||||
|
|
||||||
|
updateOrderBoxTotals()
|
||||||
let doc = $(document)
|
let doc = $(document)
|
||||||
doc.on('click', '.nextButton', goToNextPage)
|
doc.on('click', '.nextButton', goToNextPage)
|
||||||
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=grid],[data-secondary-action=grid]', gridButtonClicked)
|
||||||
|
doc.on('click', '.closeGrid', hideGrids)
|
||||||
|
doc.on('click', '.freetextButton', freetext)
|
||||||
|
doc.on('click', '.openItemButton', customItem)
|
||||||
|
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('click', '.changeCoverNumberButton', changeCoverNumberPrompt)
|
||||||
|
doc.on('click', '.showCoverSelectorButton', showCoverSelector)
|
||||||
|
doc.on('click', '.coverSelectorButton', coverSelected)
|
||||||
|
doc.on('change', '[name=print_override]', printGroupOverride)
|
||||||
|
|
||||||
|
turnOnMode('accumulate')
|
||||||
|
|
||||||
$('.loadPageGroup').first().trigger('click')
|
$('.loadPageGroup').first().trigger('click')
|
||||||
|
|
||||||
|
let observer = new window.MutationObserver((mutations, observer) => updateOrderBoxTotals())
|
||||||
|
|
||||||
|
observer.observe($('.orderBoxTable tbody').get()[0], {
|
||||||
|
subtree: true,
|
||||||
|
attributes: true,
|
||||||
|
childList: true
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 orderBox = $('.orderBoxTable tbody')
|
||||||
|
let selectedRows = orderBox.find('tr.selected')
|
||||||
|
let lastRow : JQuery = selectedRows.length ? getLastInstructionRow(selectedRows.first()) : orderBox.find('tr').last()
|
||||||
|
const existingRow = orderBox
|
||||||
|
.find('tr')
|
||||||
|
.filterByData('item', orderItem.item)
|
||||||
|
.filterByData('print_group', orderItem.print_group)
|
||||||
|
.filterByData('cover', orderItem.cover)
|
||||||
|
.last()
|
||||||
|
|
||||||
|
|
||||||
$(() => ajax('/orderScreen/getOrderScreenData/1', null, 'get', setupOrderScreen, null, null) )
|
//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)
|
||||||
|
newRow
|
||||||
|
.setColumnValue( lang('printgroup_header'), selectedRow.getColumnValue(lang('printgroup_header')) )
|
||||||
|
|
||||||
|
|
||||||
|
if(parentRow.hasClass('selected')){
|
||||||
|
selectRow(newRow)
|
||||||
|
} else {
|
||||||
|
newRow.pulse()
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollToElement(newRow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastRow = orderBox.find('tr').last()
|
||||||
|
newRow
|
||||||
|
.setColumnValue(lang('printgroup_header'), lastRow.getColumnValue(lang('printgroup_header')))
|
||||||
|
.appendTo(orderBox)
|
||||||
|
.pulse()
|
||||||
|
scrollToElement(newRow)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,
|
||||||
|
print_group: printGroup,
|
||||||
|
cover: OrderScreen.selected_cover,
|
||||||
|
}
|
||||||
|
|
||||||
|
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) => {
|
||||||
|
const existingQty = Number(row.getColumnValue(lang('qty_header')))
|
||||||
|
const newQty = qty + existingQty
|
||||||
|
row.setColumnValue(lang('qty_header'), newQty)
|
||||||
|
calculateRowTotal(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderOrderBox = () => {
|
||||||
|
const orderBox = $('.orderBoxTable')
|
||||||
|
const tbody = orderBox.children('tbody')
|
||||||
|
const newTbody = $('<tbody />')
|
||||||
|
OrderScreen.order_items.forEach(orderItem => {
|
||||||
|
const newRow = createOrderRow(orderItem)
|
||||||
|
newTbody.append(newRow)
|
||||||
|
newRow.pulse()
|
||||||
|
if(OrderScreen.selected_item_ids.includes(orderItem.id)){
|
||||||
|
selectRow(newRow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tbody.replaceWith(newTbody)
|
||||||
|
const element = orderBox.find('tbody tr').last().get()[0]
|
||||||
|
element.scrollIntoView()
|
||||||
|
OrderScreen.last_added_item = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const createOrderRow = (orderItem: orderItem) => {
|
||||||
|
const row = $('.orderBoxTable').EmptyRow()
|
||||||
|
const price = money(orderItem.item.price1)
|
||||||
|
const itemCellText = $('<span/>').text(orderItem.item.item_name)
|
||||||
|
row
|
||||||
|
.addClass(`${orderItem.item.item_type}Row`)
|
||||||
|
.setColumnValue(lang('qty_header'), orderItem.qty)
|
||||||
|
.setColumnValue(lang('price_header'), price)
|
||||||
|
.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('order-item-id', orderItem.id)
|
||||||
|
.data('print_group', orderItem.print_group)
|
||||||
|
.data('cover', orderItem.cover)
|
||||||
|
.data('item', orderItem.item)
|
||||||
|
.find('td.itemCell')
|
||||||
|
.append(itemCellText)
|
||||||
|
|
||||||
|
changeCoverOnRow(row, orderItem.cover)
|
||||||
|
|
||||||
|
if(orderItem.item.item_type == 'instruction' && price.value <= 0){
|
||||||
|
row
|
||||||
|
.find('.totalPriceCell')
|
||||||
|
.css('font-size', 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemButtonClicked = (e: JQuery.TriggeredEvent) => {
|
||||||
|
hideGrids()
|
||||||
|
const existingItemRows = $('.itemRow')
|
||||||
|
const button = $(e.target).closest('.posButton')
|
||||||
|
const item : item = button.data('item')
|
||||||
|
|
||||||
|
if(item.item_type == 'instruction' && existingItemRows.length < 1) return
|
||||||
|
|
||||||
|
const qty = OrderScreen.qty_override || 1
|
||||||
|
OrderScreen.qty_override = 1
|
||||||
|
|
||||||
|
addNewItem(item, qty)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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 row = $(e.target).closest('tr')
|
||||||
|
|
||||||
|
if(isInMode('void')){
|
||||||
|
voidRows(row)
|
||||||
|
turnOffMode('void')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!row.hasClass('selected')) selectRow(row)
|
||||||
|
else deselectRow(row)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectRow = (row: JQuery) => {
|
||||||
|
row.addClass('selected')
|
||||||
|
const instructionRows = row.nextUntil('.itemRow')
|
||||||
|
|
||||||
|
if(row.hasClass('itemRow') && instructionRows.length){
|
||||||
|
instructionRows.each((index, row) => {
|
||||||
|
selectRow($(row))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deselectRow = (row: JQuery) => {
|
||||||
|
row.removeClass('selected')
|
||||||
|
const instructionRows = row.nextUntil('.itemRow')
|
||||||
|
|
||||||
|
if(row.hasClass('itemRow') && instructionRows.length){
|
||||||
|
deselectRow(instructionRows)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteRow = (row: JQuery) => row.find('*:not(.hidden)').slideUp('fast', () => row.remove())
|
||||||
|
|
||||||
|
const voidInstructionRow = (row: JQuery) => {
|
||||||
|
if(!row.prevAll('.itemRow').first().hasClass('selected'))
|
||||||
|
deleteRow(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
const voidItemRow = (row : JQuery) => decrementQty(row)
|
||||||
|
|
||||||
|
const voidRow = (row: JQuery) => {
|
||||||
|
if(row.hasClass('itemRow')) voidItemRow(row)
|
||||||
|
else voidInstructionRow(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
const voidRows = (rows: JQuery) => rows.each((index, row) => voidRow($(row)))
|
||||||
|
|
||||||
|
const voidButtonClicked = () => {
|
||||||
|
const selectedRows = $('.orderBox tr.selected')
|
||||||
|
if(isInMode('void')){
|
||||||
|
turnOffMode('void')
|
||||||
|
} else if(selectedRows.length){
|
||||||
|
voidRows(selectedRows)
|
||||||
|
} else {
|
||||||
|
turnOnMode('void')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const voidLastItem = () => {
|
||||||
|
const orderBox = $('.orderBoxTable tbody')
|
||||||
|
const allRows = orderBox.find('tr')
|
||||||
|
if(allRows.length < 1) return
|
||||||
|
voidRows(allRows.last())
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateOrderBoxTotals = () => {
|
||||||
|
const allRows = $('.orderBoxTable tbody tr')
|
||||||
|
const selectedRows = $('.orderBoxTable tbody tr.selected')
|
||||||
|
const completeTotal = lang('totalPrice', getTotalOfRows(allRows))
|
||||||
|
const selectedTotal = lang('selectedPrice', getTotalOfRows(selectedRows))
|
||||||
|
|
||||||
|
$('.orderBoxTotal').text(completeTotal)
|
||||||
|
$('.orderBoxSelectedTotal').text(selectedTotal)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTotalOfRows = (rows: JQuery) => {
|
||||||
|
return money(rows
|
||||||
|
.find('td.totalPriceCell')
|
||||||
|
.get()
|
||||||
|
.map(cell => Number(cell.innerText))
|
||||||
|
.filter(number => !isNaN(number))
|
||||||
|
.reduce( (total, number) => total + number , 0), false)
|
||||||
|
.format()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getQty = (row: JQuery) => Number(row.getColumnValue(lang('qty_header')))
|
||||||
|
const getUnitPrice = (row: JQuery) => moneyFromString(row.getColumnValue(lang('price_header')))
|
||||||
|
const calculateRowTotal = (row: JQuery) => {
|
||||||
|
let price = getUnitPrice(row)
|
||||||
|
let qty = getQty(row)
|
||||||
|
row.setColumnValue(lang('total_price_header'), price.multiply(qty))
|
||||||
|
}
|
||||||
|
|
||||||
|
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'), existingQty - qty)
|
||||||
|
calculateRowTotal(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const freetext = () => showVirtualKeyboard('', 32,false, freetextSubmitted)
|
||||||
|
|
||||||
|
const freetextSubmitted = (text: string) => {
|
||||||
|
if(text.trim().length < 1) return
|
||||||
|
|
||||||
|
if($('.orderBoxTable tbody tr').length < 1){
|
||||||
|
posAlert(lang('freetext_no_order'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = Object.assign({}, OrderScreen.custom_item)
|
||||||
|
item.item_type = 'instruction'
|
||||||
|
item.item_name = text
|
||||||
|
|
||||||
|
addNewItem(item)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const customItem = () => showVirtualKeyboard(lang('enter_item_name'), 32,false, customItemTextSubmitted)
|
||||||
|
|
||||||
|
const customItemTextSubmitted = (text: string) => {
|
||||||
|
const submitFunction = (priceString: string) => {
|
||||||
|
const price = currency(priceString, {fromCents: false})
|
||||||
|
|
||||||
|
const item = Object.assign({}, OrderScreen.custom_item)
|
||||||
|
item.item_type = 'item'
|
||||||
|
item.item_name = text
|
||||||
|
item.price1 = price.intValue
|
||||||
|
|
||||||
|
addNewItem(item)
|
||||||
|
}
|
||||||
|
showVirtualNumpad(lang('enter_item_price'), 4, false, true, true, submitFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
53
wwwroot/scripts/ts/dredgepos.tables.ts
Normal file
53
wwwroot/scripts/ts/dredgepos.tables.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
interface JQuery {
|
||||||
|
getColumnValue(columnHeading: string) : string
|
||||||
|
setColumnValue(columnHeading: string, value: any) : JQuery
|
||||||
|
getColumnIndex(columnHeading: string) : number
|
||||||
|
EmptyRow() : JQuery<HTMLTableRowElement>
|
||||||
|
filterByData(prop: string, value: any) : JQuery
|
||||||
|
pulse() : JQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.pulse = function(this: JQuery) {
|
||||||
|
pulseElement(this)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.EmptyRow = function(this: JQuery) {
|
||||||
|
const headingRow = this.find('th').first().closest('tr')
|
||||||
|
const headingCells = headingRow.find('th')
|
||||||
|
const newRow = $('<tr/>')
|
||||||
|
headingCells.each( (index, cell) => {
|
||||||
|
const newCell = $('<td/>')
|
||||||
|
const attributes = Array.from(cell.attributes)
|
||||||
|
newCell.data('column', cell.innerText.trim())
|
||||||
|
newCell.data('column-index', index)
|
||||||
|
attributes.forEach(attribute => newCell.attr(attribute.name, attribute.value))
|
||||||
|
newRow.append(newCell)
|
||||||
|
})
|
||||||
|
|
||||||
|
return newRow as JQuery<HTMLTableRowElement>
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.getColumnIndex = function(this: JQuery, columnHeading: string){
|
||||||
|
return this
|
||||||
|
.find('td')
|
||||||
|
.filterByData('column', columnHeading)
|
||||||
|
.data('column-index')
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.getColumnValue = function(this: JQuery, columnHeading: string){
|
||||||
|
return this.find('td').filterByData('column', columnHeading).text()
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.setColumnValue = function(this: JQuery, columnHeading: string, value: any){
|
||||||
|
this.find('td').filterByData('column', columnHeading).text(value)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.filterByData = function(prop: string, val: any) {
|
||||||
|
return this.filter(
|
||||||
|
function() {
|
||||||
|
return $(this).data(prop)==val
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,26 @@
|
|||||||
type PosMode = "edit" | "void" | "transfer" | "default" | "tableSelected" | "decorationSelected" | "activeTableSelected" | "merge" | "reservedTableSelected"
|
type PosMode = "edit" | "void" | "transfer" | "default" | "tableSelected" | "decorationSelected" | "activeTableSelected" | "merge" | "reservedTableSelected" | "accumulate"
|
||||||
type PosModes = PosMode[]
|
type PosModes = PosMode[]
|
||||||
|
|
||||||
|
interface order {
|
||||||
|
clerk: string
|
||||||
|
split: boolean
|
||||||
|
items: orderItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface orderItem {
|
||||||
|
id: number
|
||||||
|
qty: number
|
||||||
|
print_group: print_group
|
||||||
|
item: item
|
||||||
|
cover: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface print_group {
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
printer: number,
|
||||||
|
venue_id: number,
|
||||||
|
}
|
||||||
|
|
||||||
interface ajaxResult {
|
interface ajaxResult {
|
||||||
status: string
|
status: string
|
||||||
@@ -13,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
|
||||||
@@ -52,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 {
|
||||||
@@ -69,3 +89,27 @@ interface keyboard {
|
|||||||
interface order_screen_page{id: number; order_screen_page_group_id: number; grid_id: number}
|
interface order_screen_page{id: number; order_screen_page_group_id: number; grid_id: number}
|
||||||
interface grid {id: number; grid_name: string; grid_rows: number; grid_cols: number; grid_data: string}
|
interface grid {id: number; grid_name: string; grid_rows: number; grid_cols: number; grid_data: string}
|
||||||
|
|
||||||
|
interface item {
|
||||||
|
id: number
|
||||||
|
item_code: string
|
||||||
|
item_category: number
|
||||||
|
item_name: string
|
||||||
|
item_type: string
|
||||||
|
price1: number
|
||||||
|
price2: number
|
||||||
|
price3: number
|
||||||
|
price4: number
|
||||||
|
price5: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type sales_category = {
|
||||||
|
id: number
|
||||||
|
parent: number
|
||||||
|
name: string
|
||||||
|
print_group: string
|
||||||
|
venue_id: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Array<T> {
|
||||||
|
where(property: string, value: any): T
|
||||||
|
}
|
||||||
36
wwwroot/scripts/ts/typings/currency.d.ts
vendored
36
wwwroot/scripts/ts/typings/currency.d.ts
vendored
@@ -1,26 +1,26 @@
|
|||||||
declare namespace currency {
|
declare namespace currency {
|
||||||
type Any = number | string | currency;
|
type Any = number | string | currency;
|
||||||
type Format = (currency?: currency, opts?: Options) => string;
|
type Format = (currency?: currency, opts?: Options) => string;
|
||||||
interface Constructor {
|
interface Constructor {
|
||||||
(value: currency.Any, opts?: currency.Options): currency,
|
(value: currency.Any, opts?: currency.Options): currency,
|
||||||
new(value: currency.Any, opts?: currency.Options): currency
|
new(value: currency.Any, opts?: currency.Options): currency
|
||||||
}
|
}
|
||||||
interface Options {
|
interface Options {
|
||||||
symbol?: string,
|
symbol?: string,
|
||||||
separator?: string,
|
separator?: string,
|
||||||
decimal?: string,
|
decimal?: string,
|
||||||
errorOnInvalid?: boolean,
|
errorOnInvalid?: boolean,
|
||||||
precision?: number,
|
precision?: number,
|
||||||
increment?: number,
|
increment?: number,
|
||||||
useVedic?: boolean,
|
useVedic?: boolean,
|
||||||
pattern?: string,
|
pattern?: string,
|
||||||
negativePattern?: string,
|
negativePattern?: string,
|
||||||
format?: currency.Format,
|
format?: currency.Format,
|
||||||
fromCents?: boolean
|
fromCents?: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface currency {
|
interface currency {
|
||||||
add(number: currency.Any): currency;
|
add(number: currency.Any): currency;
|
||||||
subtract(number: currency.Any): currency;
|
subtract(number: currency.Any): currency;
|
||||||
multiply(number: currency.Any): currency;
|
multiply(number: currency.Any): currency;
|
||||||
@@ -33,6 +33,6 @@
|
|||||||
toJSON(): number;
|
toJSON(): number;
|
||||||
readonly intValue: number;
|
readonly intValue: number;
|
||||||
readonly value: number;
|
readonly value: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare const currency: currency.Constructor;
|
declare const currency: currency.Constructor;
|
||||||
|
|||||||
@@ -15,3 +15,12 @@
|
|||||||
--posbutton-background-active: #20282D -webkit-gradient(linear, left top, left bottom, color-stop(3%,#20282D), color-stop(51%,#252E34), color-stop(100%,#222A30)) 0 top
|
--posbutton-background-active: #20282D -webkit-gradient(linear, left top, left bottom, color-stop(3%,#20282D), color-stop(51%,#252E34), color-stop(100%,#222A30)) 0 top
|
||||||
--void-button-background: red -webkit-gradient(linear, left top, left bottom, color-stop(3%,darkred), color-stop(51%,darkred), color-stop(100%,red)) 0 top
|
--void-button-background: red -webkit-gradient(linear, left top, left bottom, color-stop(3%,darkred), color-stop(51%,darkred), color-stop(100%,red)) 0 top
|
||||||
|
|
||||||
|
/** Order Screen **/
|
||||||
|
--orderbox-header-background: #888
|
||||||
|
--orderbox-row-background: var(--pos-header-background)
|
||||||
|
--orderbox-selected-row-background: #dd7f37
|
||||||
|
|
||||||
|
/** Order Box/Payment Splitter Box **/
|
||||||
|
--pulse-first-color: #ffa93e
|
||||||
|
--pulse-second-color: #dd7f37
|
||||||
|
--pulse-final-color: var(--orderbox-row-background)
|
||||||
|
|||||||
@@ -3,6 +3,15 @@
|
|||||||
src: url("/fonts/OpenSans-Regular.ttf") format('truetype')
|
src: url("/fonts/OpenSans-Regular.ttf") format('truetype')
|
||||||
font-style: normal
|
font-style: normal
|
||||||
|
|
||||||
|
@font-face
|
||||||
|
font-family: "manrope"
|
||||||
|
src: url("/fonts/OpenSans-SemiBold.ttf") format('truetype')
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
|
@font-face
|
||||||
|
font-family: "manrope"
|
||||||
|
src: url("/fonts/OpenSans-Light.ttf") format('truetype')
|
||||||
|
font-weight: 100
|
||||||
|
|
||||||
*
|
*
|
||||||
margin: 0
|
margin: 0
|
||||||
@@ -11,9 +20,19 @@
|
|||||||
font-family: 'manrope', sans-serif
|
font-family: 'manrope', sans-serif
|
||||||
scroll-behavior: smooth
|
scroll-behavior: smooth
|
||||||
|
|
||||||
|
*:not(input, textarea)
|
||||||
|
-webkit-touch-callout: none
|
||||||
|
-webkit-user-select: none
|
||||||
|
-khtml-user-select: none
|
||||||
|
-moz-user-select: none
|
||||||
|
-ms-user-select: none
|
||||||
|
user-select: none
|
||||||
|
|
||||||
.rtl
|
.rtl
|
||||||
direction: rtl
|
direction: rtl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
input[type=text], select, textarea
|
input[type=text], select, textarea
|
||||||
padding-left: 1em
|
padding-left: 1em
|
||||||
padding-right: 1em
|
padding-right: 1em
|
||||||
@@ -28,6 +47,7 @@ input[type=text], select, textarea
|
|||||||
bottom: 0
|
bottom: 0
|
||||||
left: 0
|
left: 0
|
||||||
right: 0
|
right: 0
|
||||||
|
z-index: 999
|
||||||
|
|
||||||
@mixin mobile
|
@mixin mobile
|
||||||
@media screen and (max-width: 900px)
|
@media screen and (max-width: 900px)
|
||||||
@@ -80,9 +100,26 @@ body
|
|||||||
|
|
||||||
.posButton.active, .posButton:active
|
.posButton.active, .posButton:active
|
||||||
border: inset 2px
|
border: inset 2px
|
||||||
|
background: var(--posbutton-background-active)
|
||||||
|
|
||||||
.posButton.voidButton
|
.posButton.voidButton
|
||||||
background: var(--void-button-background)
|
background: var(--void-button-background)
|
||||||
|
|
||||||
.invisible
|
.invisible
|
||||||
visibility: hidden
|
visibility: hidden
|
||||||
|
|
||||||
|
.hidden
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.pulse
|
||||||
|
animation-name: color
|
||||||
|
animation-duration: 300ms
|
||||||
|
animation-iteration-count: 1
|
||||||
|
|
||||||
|
@keyframes color
|
||||||
|
0%
|
||||||
|
background-color: var(--pulse-first-color)
|
||||||
|
50%
|
||||||
|
background-color: var(--pulse-second-color)
|
||||||
|
100%
|
||||||
|
background-color: var(--pulse-final-color)
|
||||||
@@ -26,13 +26,35 @@
|
|||||||
.orderBox
|
.orderBox
|
||||||
flex-basis: 75%
|
flex-basis: 75%
|
||||||
background: var(--global-bgcolor)
|
background: var(--global-bgcolor)
|
||||||
|
overflow-y: auto
|
||||||
|
|
||||||
.orderBoxInfo
|
.orderBoxInfo
|
||||||
|
@include flex
|
||||||
flex-basis: 5%
|
flex-basis: 5%
|
||||||
background-color: white
|
background-color: white
|
||||||
|
|
||||||
|
.voidModeWarning
|
||||||
|
@include flex
|
||||||
|
@include flex-item
|
||||||
|
color: red
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
.orderBoxFooter
|
.orderBoxFooter
|
||||||
flex-basis: 10%
|
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
|
||||||
|
font-size: 1.3em
|
||||||
|
> .orderBoxSelectedTotal
|
||||||
|
align-items: flex-start
|
||||||
|
font-size: 0.9em
|
||||||
|
|
||||||
#rightColumn
|
#rightColumn
|
||||||
@include flex-column
|
@include flex-column
|
||||||
@@ -48,32 +70,28 @@
|
|||||||
flex-grow: 0
|
flex-grow: 0
|
||||||
flex-shrink: 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
|
.functionButtons
|
||||||
@include flex-column-item
|
@include flex-column-item
|
||||||
@include flex
|
@include flex
|
||||||
flex-basis: 80%
|
flex-basis: 100%
|
||||||
|
|
||||||
> *
|
> .functionColumn
|
||||||
@include flex-item
|
@include flex-item
|
||||||
@include flex-column
|
@include flex-column
|
||||||
|
flex-basis: 25%
|
||||||
> *
|
> *
|
||||||
@include flex-column-item
|
@include flex-column-item
|
||||||
|
|
||||||
|
> .printGroupButtons
|
||||||
|
flex-basis: 25%
|
||||||
|
height: 100%
|
||||||
|
display: grid
|
||||||
|
grid-template-columns: repeat(2, 1fr)
|
||||||
|
grid-auto-rows: auto
|
||||||
|
|
||||||
|
> *
|
||||||
|
padding: 0.5em
|
||||||
|
|
||||||
|
|
||||||
#pageList
|
#pageList
|
||||||
@include flex
|
@include flex
|
||||||
@@ -90,7 +108,7 @@
|
|||||||
.active
|
.active
|
||||||
border-bottom: none
|
border-bottom: none
|
||||||
|
|
||||||
#pageContainer
|
#pageGroupContainer
|
||||||
@include flex-column
|
@include flex-column
|
||||||
@include flex-column-item
|
@include flex-column-item
|
||||||
justify-content: flex-end
|
justify-content: flex-end
|
||||||
@@ -100,100 +118,226 @@
|
|||||||
-ms-overflow-style: none
|
-ms-overflow-style: none
|
||||||
|
|
||||||
::-webkit-scrollbar
|
::-webkit-scrollbar
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
|
.pageGroup
|
||||||
|
/*display: inline-flex*/
|
||||||
|
@include flex-column-item
|
||||||
|
flex-basis: 100%
|
||||||
|
flex-grow: 0
|
||||||
|
overflow-x: auto
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.gridPage
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
flex-shrink: 0
|
||||||
|
flex-grow: 0
|
||||||
|
display: grid
|
||||||
|
|
||||||
|
.doubleWidth
|
||||||
|
width: calc(200%)
|
||||||
|
z-index: 10
|
||||||
|
|
||||||
|
.doubleHeight
|
||||||
|
height: calc(200%)
|
||||||
|
z-index: 10
|
||||||
|
|
||||||
|
.hasImage
|
||||||
|
.buttonImg
|
||||||
|
background-repeat: no-repeat
|
||||||
|
background-size: contain
|
||||||
|
background-position: center
|
||||||
|
background-origin: content-box
|
||||||
|
|
||||||
|
.hasImage.normal
|
||||||
|
font-size: 0.8em
|
||||||
|
.buttonImg
|
||||||
|
flex-basis: 40%
|
||||||
|
height: 100%
|
||||||
|
padding: 0.7em
|
||||||
|
justify-content: flex-end
|
||||||
|
|
||||||
|
.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-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
|
||||||
|
width: 100%
|
||||||
|
border-collapse: collapse
|
||||||
|
|
||||||
|
tr
|
||||||
|
background: var(--orderbox-row-background)
|
||||||
|
|
||||||
|
|
||||||
|
.selected
|
||||||
|
background: var(--orderbox-selected-row-background)
|
||||||
|
|
||||||
|
thead tr
|
||||||
|
background: var(--orderbox-header-background)
|
||||||
|
|
||||||
|
th
|
||||||
|
font-weight: normal
|
||||||
|
text-align: center
|
||||||
|
padding: 0.2em 0.5em
|
||||||
|
|
||||||
|
tr
|
||||||
|
td, th
|
||||||
|
text-align: center
|
||||||
|
font-size: 0.9em
|
||||||
|
|
||||||
|
td
|
||||||
|
padding: 1em 0.5em
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
|
.itemCell
|
||||||
|
text-align: center
|
||||||
|
width: 60%
|
||||||
|
|
||||||
|
.qtyCell
|
||||||
|
width: 10%
|
||||||
|
|
||||||
|
.printGroupCell
|
||||||
|
width: 20%
|
||||||
|
|
||||||
|
.totalPriceCell
|
||||||
|
width: 10%
|
||||||
|
|
||||||
|
td.itemCell
|
||||||
|
text-align: left
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
|
||||||
|
tr.instructionRow
|
||||||
|
td
|
||||||
|
font-weight: 100
|
||||||
|
td.itemCell
|
||||||
|
padding-left: 2em
|
||||||
|
small
|
||||||
|
font-size: 0
|
||||||
|
|
||||||
|
.qtyCell, .printGroupCell
|
||||||
|
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
|
.pageGroup
|
||||||
/*display: inline-flex*/
|
display: inline-flex
|
||||||
@include flex-column-item
|
|
||||||
flex-basis: 100%
|
flex-basis: 100%
|
||||||
flex-grow: 0
|
flex-grow: 0
|
||||||
overflow-x: auto
|
overflow-x: auto
|
||||||
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
|
|
||||||
width: calc(200%)
|
|
||||||
z-index: 10
|
|
||||||
|
|
||||||
.doubleHeight
|
|
||||||
height: calc(200%)
|
|
||||||
z-index: 10
|
|
||||||
|
|
||||||
.hasImage
|
|
||||||
.buttonImg
|
|
||||||
background-repeat: no-repeat
|
|
||||||
background-size: contain
|
|
||||||
background-position: center
|
|
||||||
background-origin: content-box
|
|
||||||
|
|
||||||
.hasImage.normal
|
|
||||||
font-size: 0.8em
|
|
||||||
.buttonImg
|
|
||||||
flex-basis: 40%
|
|
||||||
height: 100%
|
|
||||||
padding: 0.7em
|
|
||||||
justify-content: flex-end
|
|
||||||
|
|
||||||
.text
|
|
||||||
@include flex
|
|
||||||
justify-content: flex-start
|
|
||||||
flex-basis: 60%
|
|
||||||
height: 100%
|
|
||||||
|
|
||||||
.hasImage.doubleHeight
|
|
||||||
@include flex-column
|
|
||||||
|
|
||||||
.buttonImg
|
|
||||||
padding: 0.6em
|
|
||||||
flex-basis: 80%
|
|
||||||
width: 100%
|
|
||||||
|
|
||||||
.text
|
|
||||||
@include flex
|
|
||||||
flex-basis: 20%
|
|
||||||
width: 100%
|
|
||||||
|
|
||||||
.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
|
|
||||||
display: none
|
|
||||||
flex-basis: 15%
|
|
||||||
|
|
||||||
> *
|
|
||||||
@include flex-item
|
|
||||||
3
wwwroot/themes/restaurant/components/posButton.tpl.htm
Normal file
3
wwwroot/themes/restaurant/components/posButton.tpl.htm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<a class="posButton <!--[var:classes]-->" <!--[var: attributes]-->>
|
||||||
|
<!--[var:text]-->
|
||||||
|
</a>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<a class="reservationStatus" data-visible-in-mode='["reservedTableSelected"]'></a>
|
<a class="reservationStatus" data-visible-in-mode='["reservedTableSelected"]'></a>
|
||||||
<small class="selectedTableCovers"></small>
|
<small class="selectedTableCovers"></small>
|
||||||
</div>
|
</div>
|
||||||
<a class="posButton"><!--[lang:order_table]--></a>
|
<a class="posButton placeOrderButton"><!--[lang:order_table]--></a>
|
||||||
<a class="posButton reserveTableButton" data-invisible-in-mode='["reservedTableSelected", "activeTableSelected"]'><!--[lang:reserve_table]--></a>
|
<a class="posButton reserveTableButton" data-invisible-in-mode='["reservedTableSelected", "activeTableSelected"]'><!--[lang:reserve_table]--></a>
|
||||||
<a class="posButton unreserveTableButton" data-visible-in-mode='["reservedTableSelected"]'><!--[lang:unreserve_table]--></a>
|
<a class="posButton unreserveTableButton" data-visible-in-mode='["reservedTableSelected"]'><!--[lang:unreserve_table]--></a>
|
||||||
<a class="posButton payTableButton" data-visible-in-mode='["activeTableSelected"]'><!--[lang:pay_table]--></a>
|
<a class="posButton payTableButton" data-visible-in-mode='["activeTableSelected"]'><!--[lang:pay_table]--></a>
|
||||||
|
|||||||
@@ -1,62 +1,71 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>DredgePOS</title>
|
<title>DredgePOS</title>
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://unpkg.com/current-device/umd/current-device.min.js"></script>
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name = "viewport" content = "user-scalable = no ,shrink-to-fit=yes" />
|
<meta name = "viewport" content = "user-scalable = no ,shrink-to-fit=yes" />
|
||||||
<link rel="manifest" href="/manifest.webmanifest">
|
<link rel="manifest" href="/manifest.webmanifest">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="pageContainer">
|
<div id="pageContainer" <!--[var: containerAttributes]-->>
|
||||||
<div id="leftColumn">
|
<div id="leftColumn">
|
||||||
<h1 class="tableHeading"><!--[lang:active_table]--></h1>
|
<h1 class="tableHeading"><!--[var: orderNumber]--></h1>
|
||||||
<div class="tableInfo">
|
<div class="tableInfo">
|
||||||
<a href="#" class="posButton"><!--[lang:covers]--></a>
|
<!--[var: changeCoverNumberButton]-->
|
||||||
<a class="posHeader">Logged in as <!--[arr:clerk|clerk_name]--></a></a>
|
<a class="posButton">Logged in as <!--[arr:clerk|clerk_name]--></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="orderBox">
|
<div class="orderBox">
|
||||||
|
<table class="orderBoxTable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="orderBoxCell qtyCell"><!--[lang:qty_header]--></th>
|
||||||
|
<th class="orderBoxCell itemIdCell hidden"><!--[lang:id_header]--></th>
|
||||||
|
<th class="orderBoxCell itemCell"><!--[lang:item_header]--></th>
|
||||||
|
<th class="orderBoxCell unitPriceCell hidden"><!--[lang:price_header]--></th>
|
||||||
|
<th class="orderBoxCell totalPriceCell"><!--[lang:total_price_header]--></th>
|
||||||
|
<th class="orderBoxCell printGroupCell"><!--[lang:printgroup_header]--></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="orderBoxInfo">
|
||||||
|
<span class="voidModeWarning" data-visible-in-mode='["void"]'><!--[lang:void_mode]--></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="orderBoxInfo"></div>
|
|
||||||
<div class="orderBoxFooter">
|
<div class="orderBoxFooter">
|
||||||
|
<span class="orderBoxTotal"><!--[lang:totalPrice|0.00]--></span>
|
||||||
|
<small class="orderBoxSelectedTotal"><!--[lang:selectedPrice|0.00]--></small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="rightColumn">
|
<div id="rightColumn">
|
||||||
<div id="topHalf">
|
<div id="topHalf">
|
||||||
<div class="utilityButtons">
|
|
||||||
<a class="posButton"></a>
|
|
||||||
<a class="posButton"></a>
|
|
||||||
<a class="posButton"></a>
|
|
||||||
<a class="posButton logoutButton">×</a>
|
|
||||||
</div>
|
|
||||||
<div class="functionButtons">
|
<div class="functionButtons">
|
||||||
<div class="functionColumn">
|
<div class="printGroupButtons toggleGroup">
|
||||||
<a class="posButton"></a>
|
<input type="hidden" name="print_override" class="value" />
|
||||||
<a class="posButton"></a>
|
<!--[var:salesCategoryOverrideButtons]-->
|
||||||
<a class="posButton"></a>
|
|
||||||
<a class="posButton"></a>
|
|
||||||
<a class="posButton"></a>
|
|
||||||
<a class="posButton"></a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="functionColumn">
|
<div class="functionColumn">
|
||||||
<a class="posButton"></a>
|
<a class="posButton accumulateButton" data-active-in-mode="accumulate"><!--[lang:accumulate_function]--></a>
|
||||||
<a class="posButton"></a>
|
<a class="showCoverSelectorButton posButton"><!--[lang:select_covers]--></a>
|
||||||
<a class="posButton voidButton"><!--[lang:void]--></a>
|
</div>
|
||||||
<a class="posButton"></a>
|
<div class="functionColumn">
|
||||||
|
<a class="posButton voidButton" data-active-in-mode="void"><!--[lang:void]--></a>
|
||||||
|
<a class="posButton openItemButton"><!--[lang:custom_item_button]--></a>
|
||||||
|
<a class="freetextButton posButton"><!--[lang:freetext_button]--></a>
|
||||||
|
<a class="numpadButton posButton"><!--[lang:numpad_button]--></a>
|
||||||
|
</div>
|
||||||
|
<div class="functionColumn">
|
||||||
|
<a class="posButton"><!--[lang:pay_function]--></a>
|
||||||
|
<a class="posButton"><!--[lang:print_function]--></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="functionColumn"></div>
|
|
||||||
<div class="functionColumn"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="pageList">
|
<div id="pageList">
|
||||||
<!--[var:categoryList]-->
|
<!--[var:categoryList]-->
|
||||||
</div>
|
</div>
|
||||||
<div id="pageContainer">
|
<div id="pageGroupContainer">
|
||||||
<!--[var:pageGroups]-->
|
<!--[var:pageGroups]-->
|
||||||
</div>
|
</div>
|
||||||
<div class="pageNavigation">
|
<div class="pageNavigation">
|
||||||
<a class="posButton prevButton"><!--[lang:prev_page]--></a>
|
<a class="posButton prevButton"><!--[lang:prev_page]--></a>
|
||||||
@@ -66,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>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<span class="buttonImg" style="background-image:url(images/items/<!--[var:image]-->);"></span>
|
<span class="buttonImg" style="background-image:url(/images/items/<!--[var:image]-->);"></span>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<a href="#" class="posButton changeCoverNumberButton"><!--[var:covers]--></a>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div class="coverSelector">
|
||||||
|
<!--[var:coverSelectorButtons]-->
|
||||||
|
</div>
|
||||||
13
wwwroot/themes/restaurant/orderScreen/grid_container.tpl.htm
Normal file
13
wwwroot/themes/restaurant/orderScreen/grid_container.tpl.htm
Normal 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>
|
||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user