The shop app gets its help panel, and its last two old screens catch up

Ask Behavision: a panel beside any screen that talks to the head-office
assistant as the signed-in user - setup questions and 'is my shop
working' answered by the same thing, without leaving the app. The
assistant's prompt now knows how the product is set up (installation
codes, adding a camera, what a placement verdict means, the model
download on first run), so it is the help and not only the analyst. A
PC running on its own has nobody to ask and gets the essentials as text.

Cameras and Customers were still on the pre-redesign markup - the add
camera drawer ran off the right edge of the window because it used a
class the new stylesheet never sized. Both are rebuilt: cameras as
picture-led cards with connection and 'proven' as two separate claims
and a placement check laid out as the two steps it is; the customer
record as a proper sheet.

mock.js renders the app in a browser with fake bindings
(?mock=fresh|standalone|claimed, dev server only), so a screen can be
put in front of somebody without a Windows build. It is how these were
reviewed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
This commit is contained in:
2026-09-19 13:22:16 +05:30
parent 4c62fc0ef3
commit 7021d5d2f5
17 changed files with 677 additions and 253 deletions

View File

@@ -522,6 +522,27 @@ func (c *Client) ForgetVisitor(ctx context.Context, id string) error {
"/api/visitors/"+url.PathEscape(id), nil, nil)
}
// AssistantTurn is one message in the help conversation. The browser holds
// the history and resends it; nothing is stored server-side.
type AssistantTurn struct {
Role string `json:"role"`
Text string `json:"text"`
}
// AssistantAnswer is the reply, and the names of what it looked at - shown to
// the user, because an assistant that silently ran a camera check would be
// alarming and naming what it consulted makes a wrong answer traceable.
type AssistantAnswer struct {
Text string `json:"text"`
Used []string `json:"used,omitempty"`
}
// Ask puts a question to the head-office assistant as this signed-in user.
func (c *Client) Ask(ctx context.Context, history []AssistantTurn) (AssistantAnswer, error) {
var out AssistantAnswer
return out, c.do(ctx, http.MethodPost, "/api/assistant", map[string]any{"history": history}, &out)
}
func (c *Client) VisitorHistory(ctx context.Context, id string, limit int) ([]Visit, error) {
var out []Visit
return out, c.do(ctx, http.MethodGet,