Merge branch 'phase/36-person-card-tabs'
ci / server (push) Failing after 4m1s
ci / client (push) Failing after 17s

This commit is contained in:
Leonid Pershin
2026-08-20 04:35:35 +03:00
29 changed files with 1458 additions and 280 deletions
+38 -2
View File
@@ -259,8 +259,9 @@ no Chemistry; a related tongue from the name set may sit beside the native at a
(01) and `conditionLabel` from the catalog bands (`целая` / `поношенная` / `порванная` /
`висит лохмотьями`). The client draws the bar and the caption; it does not compute thresholds.
`carried` is the bag — textbooks include `subject`. `carryMass` / `carryCapacity` are kilograms;
overload does not slow walking. Home and locker stay in `people.json` and are not on this card.
The people list does not include any of these fields.
overload does not slow walking. `hasLocker` is true when anything sits in a locker; `homeCount`
is how many items remain at home, not the list. The people list does not include any of these
fields. Today's history is a separate GET.
`hasAvatar` and `hasFullBody` tell the client whether PNG files already exist on disk for this
person. They are filled on the HTTP thread after the worker returns the card; generation does
@@ -313,11 +314,46 @@ not happen on this request.
],
"carryMass": 1.2,
"carryCapacity": 14,
"hasLocker": false,
"homeCount": 3,
"hasAvatar": false,
"hasFullBody": false
}
```
### `GET /api/schools/{id}/people/{personId}/log`
Today's history for one person: search, sort by time, page. Goes through the school's mailbox
because the log lives on the worker, not in `people.json` and not on a published snapshot.
Unknown school is `404` `unknown-school`; unknown person is `404` `unknown-person`. This is
not a socket feed and not a school-wide event list.
The day boundary is six in the morning — the same hour skip lands on. Crossing that hour, or
skipping an empty night, drops yesterday's rows. `?lang=ru|en` labels the captions. `q` is a
substring of the caption or type. `sort` is `time`. `dir` is `asc` or `desc` (default `desc`).
`page` starts at 1; `pageSize` defaults to 20 and is at most 100. A thousand rows do not
arrive in one response.
Row `type` values: `action-started`, `action-ended`, `apparel-replaced` (morning issue, when
phase 34 appends it), `apparel-changed` (dressing, when phase 35 appends it). `thingDef` is
the action or apparel def the caption was built from.
```json
{
"total": 2,
"page": 1,
"pageSize": 20,
"entries": [
{
"time": "2012-04-03T12:00:00Z",
"type": "action-started",
"label": "начал: Обед",
"thingDef": "EatLunch"
}
]
}
```
### `GET /api/schools/{id}/people/{personId}/portrait`
Returns a generated PNG when one exists. Query `kind=avatar|full` selects head-and-shoulders or