There is a tablet outside the restaurant door and another inside at the counter. Both look at the same line.
That is harder than it sounds. The person at the door writes customers in; the person at the counter calls the next party. The moment the two screens each start remembering "four parties right now", the counter seats one and the door still says four. And that mismatch shows up as an argument with a customer. A good part of what companies selling queue tools by monthly subscription actually sell is preventing that mismatch.
We built it with one server and two screens.
At the door

One big number, one estimate, a list. That is everything the door screen does.
The "next", "1 ahead", "2 ahead" in the list are not stored. Where you are in the line comes out of the list's order.
// Position is derived from the list order. Nothing stores
// "you are third" — that would be wrong the moment somebody
// ahead gives up and leaves.
'ahead': i == 0 ? 'next' : '$i ahead',
If a party ahead gives up and leaves, the ones behind move up a place automatically. Had it been stored, somebody would have to rewrite all of it.
At the counter

#41 Han (2) on the right, and a button that carries that partyThe counter screen sees the same line differently. It is not for showing customers, so how long each party has waited is attached.
counter sees the same 4 parties, front of the line has waited 20 min
the same 4 parties — that line is half this article. Both screens asked the server separately and got the same answer.
Calling
Press the button at the counter and the party at the front is seated.

#42 Oduya (4), and THIS SHIFT reads seated 1, average wait 20 min, quoted now 27 minTwo things happen at once here. They leave the list and stay in the record.
// The party leaves the waiting list but not the record. An owner who
// wants to know how long people actually waited has to be able to ask
// afterwards, and a deleted row cannot answer.
p.calledAtNote = 'waited ${_now - p.joinedAtMinute} min';
_served.add(p);
seated today: 1 — Han waited 20 min at the bottom of the screen is that record. It is exactly what is needed the moment the owner asks "what is our average wait", and a deleted row cannot answer.
And the door, which nobody touched

Nobody touched this screen. One button was pressed at the counter.
door reads: 4 parties, 11 people, about 36 min
counter called: called Han (41) — Han waited 20 min
door now reads: 3 parties, about 27 min — nobody edited this screen
estimate 36 min -> 27 min because the list is 4 -> 3
36 minutes became 27 not because somebody typed 27. The list went from four to three, and the estimate is computed from the list.
// The estimate the person at the door reads out loud.
'estimate': '${_waiting.length * _minutesPerTable} min',
_minutesPerTable is 9. It is a number the owner might change once in their life, and so that number alone sits in one place.
This content requires Developer or above
Sign in and upgrade your plan to continue reading.
View Plans