From 117af0f9b11ea666033f1cf546edc2faf8a19c09 Mon Sep 17 00:00:00 2001 From: Maurice Date: Fri, 6 Nov 2026 12:57:49 +0100 Subject: [PATCH] feat(mobile): swipe through Vacay's months and years, people and legend in sheets In the editor the months of the leave year page like the trip's days, the neighbour sliding in with the finger; in the overview the plan's years do the same (only between years the plan has, the arrows still create one). The day pager now pages anything with an id and can sit in a page's flow. The row of person and legend chips is two compact pills now: People opens a sheet to pick the member and show or hide shared calendars, Legend opens one that explains the company days and holiday calendars, which were never a choice. --- client/src/mobile/components/MDayPager.tsx | 18 +- client/src/mobile/screens/vacay/MVacay.tsx | 194 +++++++++++++----- client/src/mobile/screens/vacay/useMVacay.ts | 18 +- .../tests/unit/mobile/vacay/MVacay.test.tsx | 77 +++++-- .../unit/mobile/vacay/useMVacay.test.tsx | 13 ++ shared/src/i18n/ar/mobileVacay.ts | 2 + shared/src/i18n/az/mobileVacay.ts | 2 + shared/src/i18n/br/mobileVacay.ts | 2 + shared/src/i18n/ca/mobileVacay.ts | 2 + shared/src/i18n/cs/mobileVacay.ts | 2 + shared/src/i18n/de/mobileVacay.ts | 2 + shared/src/i18n/en/mobileVacay.ts | 2 + shared/src/i18n/es/mobileVacay.ts | 2 + shared/src/i18n/et/mobileVacay.ts | 2 + shared/src/i18n/fr/mobileVacay.ts | 2 + shared/src/i18n/gr/mobileVacay.ts | 2 + shared/src/i18n/he/mobileVacay.ts | 2 + shared/src/i18n/hu/mobileVacay.ts | 2 + shared/src/i18n/id/mobileVacay.ts | 2 + shared/src/i18n/it/mobileVacay.ts | 2 + shared/src/i18n/ja/mobileVacay.ts | 2 + shared/src/i18n/ko/mobileVacay.ts | 2 + shared/src/i18n/nl/mobileVacay.ts | 2 + shared/src/i18n/pl/mobileVacay.ts | 2 + shared/src/i18n/ru/mobileVacay.ts | 2 + shared/src/i18n/sk/mobileVacay.ts | 2 + shared/src/i18n/sv/mobileVacay.ts | 2 + shared/src/i18n/th/mobileVacay.ts | 2 + shared/src/i18n/tr/mobileVacay.ts | 2 + shared/src/i18n/uk/mobileVacay.ts | 2 + shared/src/i18n/vi/mobileVacay.ts | 2 + shared/src/i18n/zh-TW/mobileVacay.ts | 2 + shared/src/i18n/zh/mobileVacay.ts | 2 + 33 files changed, 299 insertions(+), 77 deletions(-) diff --git a/client/src/mobile/components/MDayPager.tsx b/client/src/mobile/components/MDayPager.tsx index fc0fffc5b..b40d80478 100644 --- a/client/src/mobile/components/MDayPager.tsx +++ b/client/src/mobile/components/MDayPager.tsx @@ -27,8 +27,11 @@ const SETTLE_MS = 90; /** How close to a page edge counts as resting on it. */ const REST_PX = 2; +/** Anything with an id pages: trip days, a leave year's months, the plan's years. */ +export type PagerItem = Pick; + export interface MDayPagerProps { - days: Day[]; + days: PagerItem[]; selectedDayId: number | null; onSelectDay: (dayId: number) => void; /** Draws one day. Pages other than the current one are inert and hidden @@ -38,6 +41,12 @@ export interface MDayPagerProps { locked?: boolean; /** Live-region text after a swipe lands on a day. */ describeDay: (index: number, total: number) => string; + /** + * In the page's flow instead of filling a positioned parent: the strip takes + * the height of its tallest page, for content that sits in a scrolling column + * (Vacay's month editor and year grid) rather than over the whole screen. + */ + inFlow?: boolean; } interface Page { @@ -49,7 +58,7 @@ interface Page { /** The window of pages around the selection. A selection that points at no * day (the whole-trip view, or a day deleted remotely) still gets its page, * with the first day next to it as a way back. */ -export function pagesFor(days: Day[], selectedDayId: number | null): Page[] { +export function pagesFor(days: PagerItem[], selectedDayId: number | null): Page[] { const i = days.findIndex((d) => d.id === selectedDayId); if (i < 0) { const first = days[0]; @@ -74,6 +83,7 @@ export default function MDayPager({ renderDay, locked = false, describeDay, + inFlow = false, }: MDayPagerProps) { const stripRef = useRef(null); const [announcement, setAnnouncement] = useState(''); @@ -177,7 +187,7 @@ export default function MDayPager({
{pages.map((page) => (
{renderDay(page.dayId, page.active)}
diff --git a/client/src/mobile/screens/vacay/MVacay.tsx b/client/src/mobile/screens/vacay/MVacay.tsx index 455d4d9e1..c751a4783 100644 --- a/client/src/mobile/screens/vacay/MVacay.tsx +++ b/client/src/mobile/screens/vacay/MVacay.tsx @@ -1,8 +1,9 @@ -import { Building2, ChevronLeft, ChevronRight, Eye, Minus, PenLine, Pencil, Plus, Settings2, Share2, ShieldCheck, Trash2, Unlink, UserPlus } from 'lucide-react' +import { Building2, Check, ChevronDown, ChevronLeft, ChevronRight, Eye, EyeOff, Minus, PenLine, Pencil, Plus, Settings2, Share2, ShieldCheck, Trash2, Unlink, UserPlus } from 'lucide-react' import type { LucideIcon } from 'lucide-react' import MSheet from '../../components/MSheet' import MIconBtn from '../../components/MIconBtn' import MProgress from '../../components/MProgress' +import MDayPager from '../../components/MDayPager' import { useTranslation } from '../../../i18n' import { useMVacay } from './useMVacay' import MVacayMonth from './MVacayMonth' @@ -12,6 +13,11 @@ import MVacayShareSheet from './MVacayShareSheet' import { FALLBACK_PERSON_COLOR } from './vacayDayModel' import { fmtDays } from '../../../components/Vacay/vacayFormat' +/** The company-holiday tint the calendar cells use (vacayDayModel). */ +const COMPANY_COLOR = '#F5D9A6' // theme-lint-disable: the cells' fixed company-day tint +const GLASS_PILL_BUTTON = 'inline-flex h-8 flex-none items-center gap-2 rounded-full border border-[color:var(--m-gbr)] bg-[color:var(--m-glass)] px-3 text-[0.75rem] font-bold text-m-ink backdrop-blur-[24px] backdrop-saturate-[1.7] transition-transform active:scale-[.97]' +const SHEET_ROW = 'flex items-center gap-3 rounded-[16px] border border-[color:var(--m-gbr)] bg-[color:var(--m-glass)] px-4 py-3 text-start text-[0.875rem] font-bold transition-transform active:scale-[.98]' + const WEEKDAY_KEYS_MONDAY = ['vacay.mon', 'vacay.tue', 'vacay.wed', 'vacay.thu', 'vacay.fri', 'vacay.sat', 'vacay.sun'] as const const WEEKDAY_KEYS_SUNDAY = ['vacay.sun', 'vacay.mon', 'vacay.tue', 'vacay.wed', 'vacay.thu', 'vacay.fri', 'vacay.sat'] as const @@ -41,6 +47,14 @@ export default function MVacay() { ? (stat.remaining < 0 ? 'var(--m-st-danger)' : 'var(--m-st-pending)') : v.selectedColor const weekdayKeys = v.weekStart === 0 ? WEEKDAY_KEYS_SUNDAY : WEEKDAY_KEYS_MONDAY + // People to pick between: fused members, or shared calendars to show or hide. + const peopleChoosable = v.users.length > 1 || v.incomingShares.length > 0 + const legendItems = [ + ...(v.companyHolidaysEnabled ? [{ key: 'company', color: COMPANY_COLOR, label: t('mobileVacay.companyLegend') }] : []), + ...(v.holidaysEnabled ? (v.plan?.holiday_calendars ?? []).map(cal => ({ key: `cal-${cal.id}`, color: cal.color, label: cal.label || cal.region })) : []), + ] + const yearPages = v.years.map(year => ({ id: year })) + const monthPages = v.months.map((_, slot) => ({ id: slot })) return ( // h-dvh, not h-full: the shell stopped providing a definite height (#1809). @@ -121,56 +135,64 @@ export default function MVacay() {
)} - {/* Person + legend chips */} -
- {v.users.map(u => { - const color = u.color || FALLBACK_PERSON_COLOR - const active = u.id === v.selectedUserId - return ( + {/* Who the calendar is for, and what its colours mean: two compact pills + instead of a row of chips. Only the people are a choice; the legend is + explanation, so it waits behind its own pill. */} + {(peopleChoosable || legendItems.length > 0) && ( +
+ {peopleChoosable && ( - ) - })} - {/* Shared read-only calendars: tap toggles that person's ring overlay. */} - {v.incomingShares.map(s => ( - - ))} - {v.companyHolidaysEnabled && ( - - )} - {v.holidaysEnabled && (v.plan?.holiday_calendars ?? []).map(cal => ( - - ))} -
+ )} + {legendItems.length > 0 && ( + + )} +
+ )} {/* Year grid */} + {/* Swipe between the plan's years, like pages. The neighbouring year + draws its calendar at once; its entries arrive once it lands. */} {!edit && ( + String(v.years[i] ?? '')} + renderDay={pageYear => (
{/* Twelve months from the window start (#737) — Jan–Dec on a calendar year, Jul–Jun once the leave year is shifted. */} - {v.months.map(({ year, month }, slot) => ( + {v.monthsFor(pageYear ?? v.selectedYear).map(({ year, month }, slot) => (
{/* The month name is the comfortable way into the editor: the mini cells below it are ~21px on a phone, precise enough to navigate @@ -196,6 +218,8 @@ export default function MVacay() {
))}
+ )} + /> )} {/* Edit view: month quick nav + single month */} @@ -219,12 +243,23 @@ export default function MVacay() { ))} + {/* Swipe between the months of the window, like pages. */} + v.monthNameLongFor(i)} + renderDay={pageSlot => { + const slot = pageSlot ?? v.monthSlot + const m = v.months[slot] ?? v.activeMonth + return (
- {v.monthNameLong} + {v.monthNameLongFor(slot)} @@ -235,8 +270,8 @@ export default function MVacay() { ))}
+ ) + }} + /> )} @@ -338,6 +376,66 @@ export default function MVacay() { v.setSheet(null)} /> v.setSheet(null)} /> v.setSheet(null)} /> + v.setSheet(null)} variant="bottom" ariaLabel={t('mobileVacay.people')}> +
+
{t('mobileVacay.people')}
+
+ {v.users.map(u => { + const color = u.color || FALLBACK_PERSON_COLOR + const active = u.id === v.selectedUserId + return ( + + ) + })} +
+ {/* Shared read-only calendars: a tap shows or hides that person's ring overlay. */} + {v.incomingShares.length > 0 && ( + <> +
{t('vacay.sharedCalendars')}
+
+ {v.incomingShares.map(sh => ( + + ))} +
+ + )} +
+
+ v.setSheet(null)} variant="bottom" ariaLabel={t('mobileVacay.legend')}> +
+
{t('mobileVacay.legend')}
+
+ {legendItems.map(item => ( +
+ + {item.label} +
+ ))} +
+
+
- - {label} - - ) -} /** Forced Fusion-request card — stays open until accepted or declined. */ function MVacayIncomingInvite({ invites, onAccept, onDecline }: { diff --git a/client/src/mobile/screens/vacay/useMVacay.ts b/client/src/mobile/screens/vacay/useMVacay.ts index 8f7e5bea7..5026b051a 100644 --- a/client/src/mobile/screens/vacay/useMVacay.ts +++ b/client/src/mobile/screens/vacay/useMVacay.ts @@ -14,7 +14,7 @@ import { export type MVacayView = 'grid' | 'edit' export type MVacayMode = VacayMode -export type MVacaySheet = 'invite' | 'settings' | 'share' | null +export type MVacaySheet = 'invite' | 'settings' | 'share' | 'people' | 'legend' | null /** * Screen state of the mobile Vacay experience. Data loading, WebSocket sync @@ -96,6 +96,14 @@ export function useMVacay() { [locale, activeMonth], ) + // The pagers draw the neighbours of the open month and year too: the long name + // of any slot of the window, and the twelve months of any year. + const monthNameLongFor = useCallback((slot: number) => { + const m = months[slot] ?? months[0] + return new Intl.DateTimeFormat(locale, { month: 'long' }).format(new Date(m.year, m.month, 1)) + }, [locale, months]) + const monthsFor = useCallback((year: number) => windowMonths(year, yearSettings), [yearSettings]) + const selectedUser = users.find(u => u.id === selectedUserId) const selectedColor = selectedUser?.color || FALLBACK_PERSON_COLOR const selectedStat = stats.find(s => s.user_id === selectedUserId) @@ -156,6 +164,12 @@ export function useMVacay() { else { await handleAddPrevYear(); setSelectedYear(selectedYear - 1) } }, [years, selectedYear, setSelectedYear, handleAddPrevYear]) + // A swipe only moves between years the plan already has; creating one stays + // with the arrows, where it is a deliberate step. + const selectYear = useCallback((year: number) => { + if (years.includes(year)) setSelectedYear(year) + }, [years, setSelectedYear]) + const nextYear = useCallback(async () => { const idx = years.indexOf(selectedYear) if (idx >= 0 && idx < years.length - 1) setSelectedYear(years[idx + 1]) @@ -172,7 +186,7 @@ export function useMVacay() { const tripDotColor = users.find(u => u.id === currentUser?.id)?.color || 'var(--m-st-info)' return { - loading, plan, selectedYear, + loading, plan, selectedYear, years, selectYear, monthsFor, monthNameLongFor, users, isFused, currentUser, incomingInvites, acceptInvite, declineInvite, incomingShares, toggleShareHidden, diff --git a/client/tests/unit/mobile/vacay/MVacay.test.tsx b/client/tests/unit/mobile/vacay/MVacay.test.tsx index 0f8ccb968..ae7bfe9bb 100644 --- a/client/tests/unit/mobile/vacay/MVacay.test.tsx +++ b/client/tests/unit/mobile/vacay/MVacay.test.tsx @@ -45,6 +45,14 @@ const dayCtx: DayVisualContext = { }; const MONTHS_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; +const MONTHS_LONG = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + +// The paging itself is MDayPager's, tested there. This draws only the current +// page, so the year grid and the month editor under test are the ones on screen. +vi.mock('../../../../src/mobile/components/MDayPager', () => ({ + default: (props: { selectedDayId: number | null; renderDay: (id: number | null, active: boolean) => unknown }) => + props.renderDay(props.selectedDayId, true), +})); /** The screen flips the modifier flags with an updater, so the mock has to run it. */ function boolSetter() { @@ -58,6 +66,10 @@ function buildV(over: Record = {}): Record { loading: false, plan: { id: 1, holiday_calendars: [] }, selectedYear: 2026, + years: [2026], + selectYear: vi.fn((_year: number) => undefined), + monthsFor: (_year: number) => Array.from({ length: 12 }, (_, m) => ({ year: 2026, month: m })), + monthNameLongFor: (slot: number) => MONTHS_LONG[slot], users: [ { id: 1, username: 'alice', color: '#3b82f6' }, { id: 2, username: 'bob', color: null }, @@ -218,19 +230,30 @@ describe('MVacay', () => { expect(screen.queryByRole('button', { name: 'Increase allowance' })).not.toBeInTheDocument(); }); - it('FE-MOB-MVACSCR-010: person chips select their member and fall back on the shared color', () => { + it('FE-MOB-MVACSCR-010: the people pill opens the people sheet, where a member is picked', () => { render(); - - const bobChip = screen.getByRole('button', { name: 'bob' }); - const swatch = bobChip.querySelector('span') as HTMLElement; - expect(swatch.style.background).toBe('rgb(99, 102, 241)'); - - fireEvent.click(bobChip); - expect(mocks.v.selectPerson).toHaveBeenCalledWith(2); + fireEvent.click(screen.getByRole('button', { name: /People/ })); + expect(mocks.v.setSheet).toHaveBeenCalledWith('people'); }); - it('FE-MOB-MVACSCR-011: shared chips toggle their overlay and report their state', () => { + it('FE-MOB-MVACSCR-010b: in the people sheet a member is picked, falling back on the shared color', async () => { + mocks.v = buildV({ sheet: 'people' }); + render(); + + const sheet = await screen.findByRole('dialog', { name: 'People' }); + const bobRow = within(sheet).getByRole('button', { name: 'bob' }); + const swatch = bobRow.querySelector('span') as HTMLElement; + expect(swatch.style.background).toBe('rgb(99, 102, 241)'); + expect(within(sheet).getByRole('button', { name: 'alice' })).toHaveAttribute('aria-pressed', 'true'); + + fireEvent.click(bobRow); + expect(mocks.v.selectPerson).toHaveBeenCalledWith(2); + expect(mocks.v.setSheet).toHaveBeenLastCalledWith(null); + }); + + it('FE-MOB-MVACSCR-011: shared calendars toggle their overlay from the people sheet and report their state', async () => { mocks.v = buildV({ + sheet: 'people', incomingShares: [ { id: 7, owner_id: 3, username: 'carol', color: '#f59e0b', hidden: false }, { id: 8, owner_id: 4, username: 'dan', color: '#10b981', hidden: true }, @@ -238,8 +261,9 @@ describe('MVacay', () => { }); render(); - const carol = screen.getByRole('button', { name: 'carol' }); - const dan = screen.getByRole('button', { name: 'dan' }); + const sheet = await screen.findByRole('dialog', { name: 'People' }); + const carol = within(sheet).getByRole('button', { name: 'carol' }); + const dan = within(sheet).getByRole('button', { name: 'dan' }); expect(carol).toHaveAttribute('aria-pressed', 'true'); expect(dan).toHaveAttribute('aria-pressed', 'false'); @@ -249,8 +273,14 @@ describe('MVacay', () => { expect(mocks.v.toggleShareHidden).toHaveBeenNthCalledWith(2, 8, false); }); - it('FE-MOB-MVACSCR-012: shows the company legend and every enabled holiday calendar', () => { - mocks.v = buildV({ + it('FE-MOB-MVACSCR-011b: a single member with nothing shared gets no people pill', () => { + mocks.v = buildV({ users: [{ id: 1, username: 'alice', color: '#3b82f6' }] }); + render(); + expect(screen.queryByRole('button', { name: /People/ })).not.toBeInTheDocument(); + }); + + it('FE-MOB-MVACSCR-012: the legend waits behind its pill and lists the company days and every holiday calendar', async () => { + const holidays = { holidaysEnabled: true, plan: { id: 1, @@ -259,12 +289,21 @@ describe('MVacay', () => { { id: 2, region: 'NL', label: null, color: '#bbf7d0' }, ], }, - }); - render(); + }; + mocks.v = buildV(holidays); + const { unmount } = render(); + // Not on screen until asked for. + expect(screen.queryByText('Germany')).not.toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: /Legend/ })); + expect(mocks.v.setSheet).toHaveBeenCalledWith('legend'); + unmount(); - expect(screen.getByText('Company days')).toBeInTheDocument(); - expect(screen.getByText('Germany')).toBeInTheDocument(); - expect(screen.getByText('NL')).toBeInTheDocument(); + mocks.v = buildV({ ...holidays, sheet: 'legend' }); + render(); + const sheet = await screen.findByRole('dialog', { name: 'Legend' }); + expect(within(sheet).getByText('Company days')).toBeInTheDocument(); + expect(within(sheet).getByText('Germany')).toBeInTheDocument(); + expect(within(sheet).getByText('NL')).toBeInTheDocument(); }); it('FE-MOB-MVACSCR-013: the year grid shows twelve month cards and reports day taps', () => { @@ -315,7 +354,7 @@ describe('MVacay', () => { mocks.v = buildV({ view: 'edit' }); render(); - // The person chip row carries the same name; the mode switch comes last. + // The mode switch carries the selected person's name. const person = screen.getAllByRole('button', { name: 'alice' }); fireEvent.click(person[person.length - 1]); expect(mocks.v.setMode).toHaveBeenLastCalledWith('vacation'); diff --git a/client/tests/unit/mobile/vacay/useMVacay.test.tsx b/client/tests/unit/mobile/vacay/useMVacay.test.tsx index 8e166b177..cdad4612e 100644 --- a/client/tests/unit/mobile/vacay/useMVacay.test.tsx +++ b/client/tests/unit/mobile/vacay/useMVacay.test.tsx @@ -250,6 +250,19 @@ describe('useMVacay', () => { expect(result.current.monthSlot).toBe(11); }); + it('FE-MOB-MVAC-012b: a swipe selects only years the plan has, and names any slot and any year', async () => { + const setSelectedYear = vi.fn((_year: number) => undefined); + mocks.vacay = buildVacay({ years: [2025, 2026], setSelectedYear }); + const { result } = await mount(); + + act(() => { result.current.selectYear(2025); }); + act(() => { result.current.selectYear(2031); }); + expect(setSelectedYear.mock.calls).toEqual([[2025]]); + + expect(result.current.monthsFor(2025)[0]).toEqual({ year: 2025, month: 0 }); + expect(result.current.monthNameLongFor(0)).toMatch(/jan/i); + }); + it('FE-MOB-MVAC-013: only a fused plan allows selecting another member', async () => { const { result } = await mount(); diff --git a/shared/src/i18n/ar/mobileVacay.ts b/shared/src/i18n/ar/mobileVacay.ts index aaebeb9ff..0329c4966 100644 --- a/shared/src/i18n/ar/mobileVacay.ts +++ b/shared/src/i18n/ar/mobileVacay.ts @@ -24,6 +24,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'أيام الشركة', 'mobileVacay.editCalendar': 'تحرير التقويم', 'mobileVacay.viewYear': 'عرض السنة', + 'mobileVacay.people': 'الأشخاص', + 'mobileVacay.legend': 'المفتاح', }; export default mobileVacay; diff --git a/shared/src/i18n/az/mobileVacay.ts b/shared/src/i18n/az/mobileVacay.ts index 249261164..33d6ef107 100644 --- a/shared/src/i18n/az/mobileVacay.ts +++ b/shared/src/i18n/az/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Şirkət günləri', 'mobileVacay.editCalendar': 'Təqvimi redaktə et', 'mobileVacay.viewYear': 'İlə bax', + 'mobileVacay.people': 'İnsanlar', + 'mobileVacay.legend': 'İzahat', }; export default mobileVacay; diff --git a/shared/src/i18n/br/mobileVacay.ts b/shared/src/i18n/br/mobileVacay.ts index ed69348ce..3271db235 100644 --- a/shared/src/i18n/br/mobileVacay.ts +++ b/shared/src/i18n/br/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Férias coletivas', 'mobileVacay.editCalendar': 'Editar calendário', 'mobileVacay.viewYear': 'Ver ano', + 'mobileVacay.people': 'Pessoas', + 'mobileVacay.legend': 'Legenda', }; export default mobileVacay; diff --git a/shared/src/i18n/ca/mobileVacay.ts b/shared/src/i18n/ca/mobileVacay.ts index 4961b99cd..6aa28db1a 100644 --- a/shared/src/i18n/ca/mobileVacay.ts +++ b/shared/src/i18n/ca/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': "Dies d'empresa", 'mobileVacay.editCalendar': 'Edita el calendari', 'mobileVacay.viewYear': "Mostra l'any", + 'mobileVacay.people': 'Persones', + 'mobileVacay.legend': 'Llegenda', }; export default mobileVacay; diff --git a/shared/src/i18n/cs/mobileVacay.ts b/shared/src/i18n/cs/mobileVacay.ts index a3232de99..83e62e370 100644 --- a/shared/src/i18n/cs/mobileVacay.ts +++ b/shared/src/i18n/cs/mobileVacay.ts @@ -18,6 +18,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Firemní dny', 'mobileVacay.editCalendar': 'Upravit kalendář', 'mobileVacay.viewYear': 'Zobrazit rok', + 'mobileVacay.people': 'Lidé', + 'mobileVacay.legend': 'Legenda', }; export default mobileVacay; diff --git a/shared/src/i18n/de/mobileVacay.ts b/shared/src/i18n/de/mobileVacay.ts index fd054e67c..03c0c7f07 100644 --- a/shared/src/i18n/de/mobileVacay.ts +++ b/shared/src/i18n/de/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Betriebsferien', 'mobileVacay.editCalendar': 'Kalender bearbeiten', 'mobileVacay.viewYear': 'Jahr ansehen', + 'mobileVacay.people': 'Personen', + 'mobileVacay.legend': 'Legende', }; export default mobileVacay; diff --git a/shared/src/i18n/en/mobileVacay.ts b/shared/src/i18n/en/mobileVacay.ts index b2565fc77..1841709db 100644 --- a/shared/src/i18n/en/mobileVacay.ts +++ b/shared/src/i18n/en/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Company days', 'mobileVacay.editCalendar': 'Edit calendar', 'mobileVacay.viewYear': 'View year', + 'mobileVacay.people': 'People', + 'mobileVacay.legend': 'Legend', }; export default mobileVacay; diff --git a/shared/src/i18n/es/mobileVacay.ts b/shared/src/i18n/es/mobileVacay.ts index 933391afc..267c3c4bc 100644 --- a/shared/src/i18n/es/mobileVacay.ts +++ b/shared/src/i18n/es/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Días de empresa', 'mobileVacay.editCalendar': 'Editar calendario', 'mobileVacay.viewYear': 'Ver año', + 'mobileVacay.people': 'Personas', + 'mobileVacay.legend': 'Leyenda', }; export default mobileVacay; diff --git a/shared/src/i18n/et/mobileVacay.ts b/shared/src/i18n/et/mobileVacay.ts index d341518ca..cf8b8fd40 100644 --- a/shared/src/i18n/et/mobileVacay.ts +++ b/shared/src/i18n/et/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Ettevõtte puhkepäevad', 'mobileVacay.editCalendar': 'Muuda kalendrit', 'mobileVacay.viewYear': 'Vaata aastat', + 'mobileVacay.people': 'Inimesed', + 'mobileVacay.legend': 'Legend', // same-as-en }; export default mobileVacay; diff --git a/shared/src/i18n/fr/mobileVacay.ts b/shared/src/i18n/fr/mobileVacay.ts index 0bc4cabce..919d2ad91 100644 --- a/shared/src/i18n/fr/mobileVacay.ts +++ b/shared/src/i18n/fr/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': "Congés d'entreprise", 'mobileVacay.editCalendar': 'Modifier le calendrier', 'mobileVacay.viewYear': "Voir l'année", + 'mobileVacay.people': 'Personnes', + 'mobileVacay.legend': 'Légende', }; export default mobileVacay; diff --git a/shared/src/i18n/gr/mobileVacay.ts b/shared/src/i18n/gr/mobileVacay.ts index 7802b19f4..2b6369512 100644 --- a/shared/src/i18n/gr/mobileVacay.ts +++ b/shared/src/i18n/gr/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Άδεια εταιρείας', 'mobileVacay.editCalendar': 'Επεξεργασία ημερολογίου', 'mobileVacay.viewYear': 'Προβολή έτους', + 'mobileVacay.people': 'Άτομα', + 'mobileVacay.legend': 'Υπόμνημα', }; export default mobileVacay; diff --git a/shared/src/i18n/he/mobileVacay.ts b/shared/src/i18n/he/mobileVacay.ts index 4f2415e43..3bfa97fca 100644 --- a/shared/src/i18n/he/mobileVacay.ts +++ b/shared/src/i18n/he/mobileVacay.ts @@ -18,6 +18,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'ימי חברה', 'mobileVacay.editCalendar': 'עריכת לוח שנה', 'mobileVacay.viewYear': 'תצוגת שנה', + 'mobileVacay.people': 'אנשים', + 'mobileVacay.legend': 'מקרא', }; export default mobileVacay; diff --git a/shared/src/i18n/hu/mobileVacay.ts b/shared/src/i18n/hu/mobileVacay.ts index 63440a3c1..8c31fc916 100644 --- a/shared/src/i18n/hu/mobileVacay.ts +++ b/shared/src/i18n/hu/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Céges szabadság', 'mobileVacay.editCalendar': 'Naptár szerkesztése', 'mobileVacay.viewYear': 'Év megtekintése', + 'mobileVacay.people': 'Személyek', + 'mobileVacay.legend': 'Jelmagyarázat', }; export default mobileVacay; diff --git a/shared/src/i18n/id/mobileVacay.ts b/shared/src/i18n/id/mobileVacay.ts index 42e2bc676..503abf46b 100644 --- a/shared/src/i18n/id/mobileVacay.ts +++ b/shared/src/i18n/id/mobileVacay.ts @@ -14,6 +14,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Libur perusahaan', 'mobileVacay.editCalendar': 'Edit kalender', 'mobileVacay.viewYear': 'Lihat tahun', + 'mobileVacay.people': 'Orang', + 'mobileVacay.legend': 'Keterangan', }; export default mobileVacay; diff --git a/shared/src/i18n/it/mobileVacay.ts b/shared/src/i18n/it/mobileVacay.ts index 17fcf7bf4..8a6bfae96 100644 --- a/shared/src/i18n/it/mobileVacay.ts +++ b/shared/src/i18n/it/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Ferie aziendali', 'mobileVacay.editCalendar': 'Modifica calendario', 'mobileVacay.viewYear': 'Visualizza anno', + 'mobileVacay.people': 'Persone', + 'mobileVacay.legend': 'Legenda', }; export default mobileVacay; diff --git a/shared/src/i18n/ja/mobileVacay.ts b/shared/src/i18n/ja/mobileVacay.ts index 62d5d1732..6e0d5ec8c 100644 --- a/shared/src/i18n/ja/mobileVacay.ts +++ b/shared/src/i18n/ja/mobileVacay.ts @@ -14,6 +14,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': '会社の休業日', 'mobileVacay.editCalendar': 'カレンダーを編集', 'mobileVacay.viewYear': '年間を表示', + 'mobileVacay.people': 'メンバー', + 'mobileVacay.legend': '凡例', }; export default mobileVacay; diff --git a/shared/src/i18n/ko/mobileVacay.ts b/shared/src/i18n/ko/mobileVacay.ts index 6a48063a0..60777d6b1 100644 --- a/shared/src/i18n/ko/mobileVacay.ts +++ b/shared/src/i18n/ko/mobileVacay.ts @@ -14,6 +14,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': '회사 지정 휴무', 'mobileVacay.editCalendar': '캘린더 편집', 'mobileVacay.viewYear': '연간 보기', + 'mobileVacay.people': '사람', + 'mobileVacay.legend': '범례', }; export default mobileVacay; diff --git a/shared/src/i18n/nl/mobileVacay.ts b/shared/src/i18n/nl/mobileVacay.ts index 67135af90..739ebce19 100644 --- a/shared/src/i18n/nl/mobileVacay.ts +++ b/shared/src/i18n/nl/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Bedrijfsverlof', 'mobileVacay.editCalendar': 'Kalender bewerken', 'mobileVacay.viewYear': 'Jaar bekijken', + 'mobileVacay.people': 'Personen', + 'mobileVacay.legend': 'Legenda', }; export default mobileVacay; diff --git a/shared/src/i18n/pl/mobileVacay.ts b/shared/src/i18n/pl/mobileVacay.ts index b98b36d47..b3f061683 100644 --- a/shared/src/i18n/pl/mobileVacay.ts +++ b/shared/src/i18n/pl/mobileVacay.ts @@ -20,6 +20,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Dni firmowe', 'mobileVacay.editCalendar': 'Edytuj kalendarz', 'mobileVacay.viewYear': 'Zobacz rok', + 'mobileVacay.people': 'Osoby', + 'mobileVacay.legend': 'Legenda', }; export default mobileVacay; diff --git a/shared/src/i18n/ru/mobileVacay.ts b/shared/src/i18n/ru/mobileVacay.ts index c75599a48..5a7260bfa 100644 --- a/shared/src/i18n/ru/mobileVacay.ts +++ b/shared/src/i18n/ru/mobileVacay.ts @@ -20,6 +20,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Корпоративные дни', 'mobileVacay.editCalendar': 'Изменить календарь', 'mobileVacay.viewYear': 'Просмотр года', + 'mobileVacay.people': 'Люди', + 'mobileVacay.legend': 'Легенда', }; export default mobileVacay; diff --git a/shared/src/i18n/sk/mobileVacay.ts b/shared/src/i18n/sk/mobileVacay.ts index 609a16a8c..640bc26cb 100644 --- a/shared/src/i18n/sk/mobileVacay.ts +++ b/shared/src/i18n/sk/mobileVacay.ts @@ -18,6 +18,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Firemné dni', 'mobileVacay.editCalendar': 'Upraviť kalendár', 'mobileVacay.viewYear': 'Zobraziť rok', + 'mobileVacay.people': 'Ľudia', + 'mobileVacay.legend': 'Legenda', }; export default mobileVacay; diff --git a/shared/src/i18n/sv/mobileVacay.ts b/shared/src/i18n/sv/mobileVacay.ts index bcb540d87..38a2cc30f 100644 --- a/shared/src/i18n/sv/mobileVacay.ts +++ b/shared/src/i18n/sv/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Företagsledighet', 'mobileVacay.editCalendar': 'Redigera kalender', 'mobileVacay.viewYear': 'Visa år', + 'mobileVacay.people': 'Personer', + 'mobileVacay.legend': 'Teckenförklaring', }; export default mobileVacay; diff --git a/shared/src/i18n/th/mobileVacay.ts b/shared/src/i18n/th/mobileVacay.ts index 28cef054e..0e3ac0e70 100644 --- a/shared/src/i18n/th/mobileVacay.ts +++ b/shared/src/i18n/th/mobileVacay.ts @@ -14,6 +14,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'วันของบริษัท', 'mobileVacay.editCalendar': 'แก้ไขปฏิทิน', 'mobileVacay.viewYear': 'ดูปี', + 'mobileVacay.people': 'บุคคล', + 'mobileVacay.legend': 'คำอธิบายสัญลักษณ์', }; export default mobileVacay; diff --git a/shared/src/i18n/tr/mobileVacay.ts b/shared/src/i18n/tr/mobileVacay.ts index a20e491d4..f162e4708 100644 --- a/shared/src/i18n/tr/mobileVacay.ts +++ b/shared/src/i18n/tr/mobileVacay.ts @@ -16,6 +16,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Şirket tatili', 'mobileVacay.editCalendar': 'Takvimi düzenle', 'mobileVacay.viewYear': 'Yılı görüntüle', + 'mobileVacay.people': 'Kişiler', + 'mobileVacay.legend': 'Açıklama', }; export default mobileVacay; diff --git a/shared/src/i18n/uk/mobileVacay.ts b/shared/src/i18n/uk/mobileVacay.ts index 02b5ca519..72526230a 100644 --- a/shared/src/i18n/uk/mobileVacay.ts +++ b/shared/src/i18n/uk/mobileVacay.ts @@ -20,6 +20,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Корпоративні дні', 'mobileVacay.editCalendar': 'Редагувати календар', 'mobileVacay.viewYear': 'Переглянути рік', + 'mobileVacay.people': 'Люди', + 'mobileVacay.legend': 'Легенда', }; export default mobileVacay; diff --git a/shared/src/i18n/vi/mobileVacay.ts b/shared/src/i18n/vi/mobileVacay.ts index bde6b7f24..97821937f 100644 --- a/shared/src/i18n/vi/mobileVacay.ts +++ b/shared/src/i18n/vi/mobileVacay.ts @@ -14,6 +14,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': 'Ngày nghỉ công ty', 'mobileVacay.editCalendar': 'Sửa lịch', 'mobileVacay.viewYear': 'Xem năm', + 'mobileVacay.people': 'Mọi người', + 'mobileVacay.legend': 'Chú thích', }; export default mobileVacay; diff --git a/shared/src/i18n/zh-TW/mobileVacay.ts b/shared/src/i18n/zh-TW/mobileVacay.ts index ed6327a9c..e05176de6 100644 --- a/shared/src/i18n/zh-TW/mobileVacay.ts +++ b/shared/src/i18n/zh-TW/mobileVacay.ts @@ -14,6 +14,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': '公司假期', 'mobileVacay.editCalendar': '編輯日曆', 'mobileVacay.viewYear': '檢視年度', + 'mobileVacay.people': '成員', + 'mobileVacay.legend': '圖例', }; export default mobileVacay; diff --git a/shared/src/i18n/zh/mobileVacay.ts b/shared/src/i18n/zh/mobileVacay.ts index a8defcdbd..1236336c0 100644 --- a/shared/src/i18n/zh/mobileVacay.ts +++ b/shared/src/i18n/zh/mobileVacay.ts @@ -14,6 +14,8 @@ const mobileVacay: TranslationStrings = { 'mobileVacay.companyLegend': '公司假期', 'mobileVacay.editCalendar': '编辑日历', 'mobileVacay.viewYear': '查看年度', + 'mobileVacay.people': '成员', + 'mobileVacay.legend': '图例', }; export default mobileVacay;