Merge branch 'main' into phase/32-weather-warmth
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # src/HSchool.Simulation/School.cs
This commit is contained in:
@@ -303,6 +303,8 @@ export interface WornItem {
|
||||
readonly color: string | null;
|
||||
readonly colorLabel: string | null;
|
||||
readonly layers: readonly DefLabel[];
|
||||
readonly condition: number;
|
||||
readonly conditionLabel: string;
|
||||
}
|
||||
|
||||
export interface CarriedItem {
|
||||
|
||||
@@ -676,6 +676,34 @@ body {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.people__garments {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
gap: 8px 16px;
|
||||
}
|
||||
|
||||
.people__garment {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.people__wear {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 2px 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.people__wear-label {
|
||||
grid-column: 1 / -1;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.people__wear .people__need-track {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.people__tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -41,6 +41,8 @@ function card(overrides: Partial<PersonCard> = {}): PersonCard {
|
||||
color: 'White',
|
||||
colorLabel: 'Белый',
|
||||
layers: [{ defName: 'Top', label: 'Верх' }],
|
||||
condition: 1,
|
||||
conditionLabel: 'целая',
|
||||
},
|
||||
],
|
||||
carried: [
|
||||
@@ -74,4 +76,58 @@ describe('renderPersonCard', () => {
|
||||
expect(root.textContent).toContain('Учебник · Математика');
|
||||
expect(root.querySelector('.people__tabs')).toBeNull();
|
||||
});
|
||||
|
||||
it('shows the server condition caption, not a band inferred from the number', () => {
|
||||
setLocale('ru');
|
||||
const root = document.createElement('div');
|
||||
renderPersonCard(
|
||||
root,
|
||||
card({
|
||||
worn: [
|
||||
{
|
||||
defName: 'Shirt',
|
||||
label: 'Рубашка',
|
||||
color: 'White',
|
||||
colorLabel: 'Белый',
|
||||
layers: [{ defName: 'Top', label: 'Верх' }],
|
||||
condition: 0.1,
|
||||
conditionLabel: 'целая',
|
||||
},
|
||||
],
|
||||
}),
|
||||
() => {},
|
||||
);
|
||||
|
||||
expect(root.textContent).toContain('целая');
|
||||
expect(root.textContent).not.toContain('висит лохмотьями');
|
||||
expect(root.querySelector('.people__wear-label')?.textContent).toBe('целая');
|
||||
expect((root.querySelector('.people__need-fill') as HTMLElement | null)?.style.width).toBe('10%');
|
||||
});
|
||||
|
||||
it('changes the caption when the payload label crosses a threshold', () => {
|
||||
setLocale('ru');
|
||||
const root = document.createElement('div');
|
||||
renderPersonCard(root, card(), () => {});
|
||||
expect(root.querySelector('.people__wear-label')?.textContent).toBe('целая');
|
||||
|
||||
root.replaceChildren();
|
||||
renderPersonCard(
|
||||
root,
|
||||
card({
|
||||
worn: [
|
||||
{
|
||||
defName: 'Shirt',
|
||||
label: 'Рубашка',
|
||||
color: 'White',
|
||||
colorLabel: 'Белый',
|
||||
layers: [{ defName: 'Top', label: 'Верх' }],
|
||||
condition: 0.1,
|
||||
conditionLabel: 'висит лохмотьями',
|
||||
},
|
||||
],
|
||||
}),
|
||||
() => {},
|
||||
);
|
||||
expect(root.querySelector('.people__wear-label')?.textContent).toBe('висит лохмотьями');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,22 +119,36 @@ function appendApparel(parent: HTMLElement, rows: PersonCard['worn']): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const grid = el('dl', { class: 'people__pairs' });
|
||||
const list = el('div', { class: 'people__garments' });
|
||||
for (const row of rows) {
|
||||
const layers = row.layers.map((layer) => layer.label).join(', ');
|
||||
const color = row.colorLabel ?? row.color;
|
||||
const value = color !== null && color.length > 0 ? `${row.label} · ${color}` : row.label;
|
||||
grid.append(
|
||||
const share = Math.max(0, Math.min(1, row.condition));
|
||||
const fill = el('span', { class: 'people__need-fill' });
|
||||
fill.style.width = `${Math.round(share * 100)}%`;
|
||||
fill.classList.toggle('people__need-fill--low', share < 0.25);
|
||||
list.append(
|
||||
el(
|
||||
'div',
|
||||
{ class: 'people__pair' },
|
||||
el('dt', { text: layers.length > 0 ? layers : row.label }),
|
||||
el('dd', { text: value }),
|
||||
{ class: 'people__garment' },
|
||||
el(
|
||||
'div',
|
||||
{ class: 'people__pair' },
|
||||
el('dt', { text: layers.length > 0 ? layers : row.label }),
|
||||
el('dd', { text: value }),
|
||||
),
|
||||
el(
|
||||
'div',
|
||||
{ class: 'people__wear' },
|
||||
el('span', { class: 'people__wear-label', text: row.conditionLabel }),
|
||||
el('span', { class: 'people__need-track' }, fill),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
parent.append(section(t('peopleApparel')), grid);
|
||||
parent.append(section(t('peopleApparel')), list);
|
||||
}
|
||||
|
||||
function appendCarry(parent: HTMLElement, card: PersonCard): void {
|
||||
|
||||
Reference in New Issue
Block a user