Update task mode UI details
This commit is contained in:
@@ -537,13 +537,13 @@
|
|||||||
"disabledTitle": "Fotoaufgaben-Modus ist für dieses Event aus",
|
"disabledTitle": "Fotoaufgaben-Modus ist für dieses Event aus",
|
||||||
"disabledBody": "Gäste sehen nur den Fotofeed. Aktiviere Fotoaufgaben in den Event-Einstellungen, um sie wieder anzuzeigen.",
|
"disabledBody": "Gäste sehen nur den Fotofeed. Aktiviere Fotoaufgaben in den Event-Einstellungen, um sie wieder anzuzeigen.",
|
||||||
"toggle": {
|
"toggle": {
|
||||||
"title": "Fotoaufgaben für dieses Event",
|
"title": "Fotoaufgaben-Modus",
|
||||||
"description": "Gib Gästen optionale Fotoaufgaben und kleine Foto-Ideen.",
|
"description": "Steuere, ob Gäste Mission Cards und Fotoideen sehen.",
|
||||||
"active": "AKTIV",
|
"active": "AKTIV",
|
||||||
"inactive": "INAKTIV",
|
"inactive": "INAKTIV",
|
||||||
"onLabel": "Gäste sehen Fotoaufgaben",
|
"onLabel": "Mission Cards aktiv",
|
||||||
"offLabel": "Gäste sehen nur Fotos",
|
"offLabel": "Nur Fotofeed",
|
||||||
"switchLabel": "Fotoaufgaben aktiv",
|
"switchLabel": "Fotoaufgaben für Gäste",
|
||||||
"enabled": "Fotoaufgaben aktiviert",
|
"enabled": "Fotoaufgaben aktiviert",
|
||||||
"disabled": "Fotoaufgaben deaktiviert",
|
"disabled": "Fotoaufgaben deaktiviert",
|
||||||
"permissionHint": "Du hast keine Berechtigung, Fotoaufgaben zu ändern."
|
"permissionHint": "Du hast keine Berechtigung, Fotoaufgaben zu ändern."
|
||||||
@@ -561,6 +561,7 @@
|
|||||||
"limitReached": "Fotoaufgaben-Limit erreicht.",
|
"limitReached": "Fotoaufgaben-Limit erreicht.",
|
||||||
"limitReachedHint": "Dieses Event erlaubt maximal {{count}} Fotoaufgaben.",
|
"limitReachedHint": "Dieses Event erlaubt maximal {{count}} Fotoaufgaben.",
|
||||||
"limitRemaining": "{{count}} von {{total}} Fotoaufgaben verfügbar.",
|
"limitRemaining": "{{count}} von {{total}} Fotoaufgaben verfügbar.",
|
||||||
|
"remainingIndicator": "{{count}} / {{total}} übrig",
|
||||||
"limitSkipped": "{{count}} Fotoaufgaben wegen Limit übersprungen.",
|
"limitSkipped": "{{count}} Fotoaufgaben wegen Limit übersprungen.",
|
||||||
"created": "Fotoaufgabe gespeichert",
|
"created": "Fotoaufgabe gespeichert",
|
||||||
"removed": "Fotoaufgabe entfernt",
|
"removed": "Fotoaufgabe entfernt",
|
||||||
|
|||||||
@@ -533,13 +533,13 @@
|
|||||||
"disabledTitle": "Photo tasks mode is off for this event",
|
"disabledTitle": "Photo tasks mode is off for this event",
|
||||||
"disabledBody": "Guests only see the photo feed. Enable photo tasks in the event settings to show them again.",
|
"disabledBody": "Guests only see the photo feed. Enable photo tasks in the event settings to show them again.",
|
||||||
"toggle": {
|
"toggle": {
|
||||||
"title": "Photo tasks for this event",
|
"title": "Photo task mode",
|
||||||
"description": "Give guests optional photo tasks and prompts.",
|
"description": "Control whether guests see mission cards and prompts.",
|
||||||
"active": "ACTIVE",
|
"active": "ACTIVE",
|
||||||
"inactive": "INACTIVE",
|
"inactive": "INACTIVE",
|
||||||
"onLabel": "Guests see photo tasks",
|
"onLabel": "Mission cards active",
|
||||||
"offLabel": "Guest app shows photos only",
|
"offLabel": "Photo feed only",
|
||||||
"switchLabel": "Photo tasks enabled",
|
"switchLabel": "Photo tasks for guests",
|
||||||
"enabled": "Photo tasks activated",
|
"enabled": "Photo tasks activated",
|
||||||
"disabled": "Photo tasks disabled",
|
"disabled": "Photo tasks disabled",
|
||||||
"permissionHint": "You do not have permission to change photo tasks."
|
"permissionHint": "You do not have permission to change photo tasks."
|
||||||
@@ -557,6 +557,7 @@
|
|||||||
"limitReached": "Photo task limit reached.",
|
"limitReached": "Photo task limit reached.",
|
||||||
"limitReachedHint": "This event allows up to {{count}} photo tasks.",
|
"limitReachedHint": "This event allows up to {{count}} photo tasks.",
|
||||||
"limitRemaining": "{{count}} of {{total}} photo tasks remaining.",
|
"limitRemaining": "{{count}} of {{total}} photo tasks remaining.",
|
||||||
|
"remainingIndicator": "{{count}} / {{total}} tasks remaining",
|
||||||
"limitSkipped": "Skipped {{count}} tasks due to limit.",
|
"limitSkipped": "Skipped {{count}} tasks due to limit.",
|
||||||
"created": "Photo task saved",
|
"created": "Photo task saved",
|
||||||
"removed": "Photo task removed",
|
"removed": "Photo task removed",
|
||||||
|
|||||||
@@ -206,11 +206,15 @@ export default function MobileEventTasksPage() {
|
|||||||
return typeof limit === 'number' && Number.isFinite(limit) ? limit : null;
|
return typeof limit === 'number' && Number.isFinite(limit) ? limit : null;
|
||||||
}, [eventRecord?.limits?.tasks?.limit]);
|
}, [eventRecord?.limits?.tasks?.limit]);
|
||||||
const remainingTasks = React.useMemo(() => {
|
const remainingTasks = React.useMemo(() => {
|
||||||
|
const remaining = eventRecord?.limits?.tasks?.remaining;
|
||||||
|
if (typeof remaining === 'number' && Number.isFinite(remaining)) {
|
||||||
|
return Math.max(0, remaining);
|
||||||
|
}
|
||||||
if (maxTasks === null) {
|
if (maxTasks === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Math.max(0, maxTasks - assignedTasks.length);
|
return Math.max(0, maxTasks - assignedTasks.length);
|
||||||
}, [assignedTasks.length, maxTasks]);
|
}, [assignedTasks.length, eventRecord?.limits?.tasks?.remaining, maxTasks]);
|
||||||
const canAddTasks = maxTasks === null || (remainingTasks ?? 0) > 0;
|
const canAddTasks = maxTasks === null || (remainingTasks ?? 0) > 0;
|
||||||
const limitReachedMessage = t('events.tasks.limitReached', 'Photo task limit reached.');
|
const limitReachedMessage = t('events.tasks.limitReached', 'Photo task limit reached.');
|
||||||
const limitReachedHint =
|
const limitReachedHint =
|
||||||
@@ -781,9 +785,19 @@ export default function MobileEventTasksPage() {
|
|||||||
) : (
|
) : (
|
||||||
<YStack space="$2">
|
<YStack space="$2">
|
||||||
<YStack ref={assignedRef} />
|
<YStack ref={assignedRef} />
|
||||||
<Text fontSize="$sm" color={muted}>
|
<XStack alignItems="center" flexWrap="wrap" space="$2">
|
||||||
{t('events.tasks.count', '{{count}} photo tasks', { count: filteredTasks.length })}
|
<Text fontSize="$sm" color={muted}>
|
||||||
</Text>
|
{t('events.tasks.count', '{{count}} photo tasks', { count: filteredTasks.length })}
|
||||||
|
</Text>
|
||||||
|
{typeof remainingTasks === 'number' && typeof maxTasks === 'number' ? (
|
||||||
|
<Tag
|
||||||
|
label={t('events.tasks.remainingIndicator', '{{count}} / {{total}} tasks remaining', {
|
||||||
|
count: remainingTasks,
|
||||||
|
total: maxTasks,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</XStack>
|
||||||
{selectionMode ? (
|
{selectionMode ? (
|
||||||
<MobileCard padding="$2.5" space="$2">
|
<MobileCard padding="$2.5" space="$2">
|
||||||
<Text fontSize={12} fontWeight="700" color={text}>
|
<Text fontSize={12} fontWeight="700" color={text}>
|
||||||
@@ -977,7 +991,7 @@ export default function MobileEventTasksPage() {
|
|||||||
<YStack space="$1" flex={1} minWidth={180}>
|
<YStack space="$1" flex={1} minWidth={180}>
|
||||||
<XStack alignItems="center" space="$2" flexWrap="wrap">
|
<XStack alignItems="center" space="$2" flexWrap="wrap">
|
||||||
<Text fontSize="$sm" fontWeight="800" color={text}>
|
<Text fontSize="$sm" fontWeight="800" color={text}>
|
||||||
{t('events.tasks.toggle.title', 'Photo tasks for this event')}
|
{t('events.tasks.toggle.title', 'Photo task mode')}
|
||||||
</Text>
|
</Text>
|
||||||
<PillBadge tone={tasksEnabled ? 'success' : 'warning'}>
|
<PillBadge tone={tasksEnabled ? 'success' : 'warning'}>
|
||||||
{tasksEnabled
|
{tasksEnabled
|
||||||
@@ -985,21 +999,13 @@ export default function MobileEventTasksPage() {
|
|||||||
: t('events.tasks.toggle.inactive', 'INACTIVE')}
|
: t('events.tasks.toggle.inactive', 'INACTIVE')}
|
||||||
</PillBadge>
|
</PillBadge>
|
||||||
</XStack>
|
</XStack>
|
||||||
{showTaskDetails ? (
|
|
||||||
<Text fontSize="$xs" color={muted}>
|
|
||||||
{t(
|
|
||||||
'events.tasks.toggle.description',
|
|
||||||
'Give guests optional photo tasks and prompts.'
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
</YStack>
|
</YStack>
|
||||||
<XStack alignItems="center" space="$2">
|
<XStack alignItems="center" space="$2">
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={() => setShowTaskDetails((prev) => !prev)}
|
onPress={() => setShowTaskDetails((prev) => !prev)}
|
||||||
aria-label={t(
|
aria-label={t(
|
||||||
'events.tasks.toggle.description',
|
'events.tasks.toggle.description',
|
||||||
'Give guests optional photo tasks and prompts.'
|
'Control whether guests see mission cards and prompts.'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<XStack
|
<XStack
|
||||||
@@ -1015,23 +1021,36 @@ export default function MobileEventTasksPage() {
|
|||||||
<Info size={14} color={showTaskDetails ? primary : muted} />
|
<Info size={14} color={showTaskDetails ? primary : muted} />
|
||||||
</XStack>
|
</XStack>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
<Switch
|
|
||||||
size="$4"
|
|
||||||
checked={tasksEnabled}
|
|
||||||
onCheckedChange={handleTasksToggle}
|
|
||||||
aria-label={t('events.tasks.toggle.switchLabel', 'Photo tasks enabled')}
|
|
||||||
disabled={!canManageTasks || tasksToggleBusy}
|
|
||||||
>
|
|
||||||
<Switch.Thumb />
|
|
||||||
</Switch>
|
|
||||||
</XStack>
|
</XStack>
|
||||||
</XStack>
|
</XStack>
|
||||||
{showTaskDetails ? (
|
{showTaskDetails ? (
|
||||||
<Text fontSize="$xs" color={muted}>
|
<YStack space="$2">
|
||||||
{tasksEnabled
|
<Text fontSize="$xs" color={muted}>
|
||||||
? t('events.tasks.toggle.onLabel', 'Guests see photo tasks')
|
{t(
|
||||||
: t('events.tasks.toggle.offLabel', 'Guest app shows photos only')}
|
'events.tasks.toggle.description',
|
||||||
</Text>
|
'Control whether guests see mission cards and prompts.'
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
<XStack alignItems="center" justifyContent="space-between" space="$2">
|
||||||
|
<Text fontSize="$sm" fontWeight="700" color={text}>
|
||||||
|
{t('events.tasks.toggle.switchLabel', 'Photo tasks for guests')}
|
||||||
|
</Text>
|
||||||
|
<Switch
|
||||||
|
size="$4"
|
||||||
|
checked={tasksEnabled}
|
||||||
|
onCheckedChange={handleTasksToggle}
|
||||||
|
aria-label={t('events.tasks.toggle.switchLabel', 'Photo tasks for guests')}
|
||||||
|
disabled={!canManageTasks || tasksToggleBusy}
|
||||||
|
>
|
||||||
|
<Switch.Thumb />
|
||||||
|
</Switch>
|
||||||
|
</XStack>
|
||||||
|
<Text fontSize="$xs" color={muted}>
|
||||||
|
{tasksEnabled
|
||||||
|
? t('events.tasks.toggle.onLabel', 'Mission cards active')
|
||||||
|
: t('events.tasks.toggle.offLabel', 'Photo feed only')}
|
||||||
|
</Text>
|
||||||
|
</YStack>
|
||||||
) : null}
|
) : null}
|
||||||
{isMember && !canManageTasks ? (
|
{isMember && !canManageTasks ? (
|
||||||
<Text fontSize="$xs" color={muted}>
|
<Text fontSize="$xs" color={muted}>
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ describe('MobileEventTasksPage', () => {
|
|||||||
it('renders the quick jump chips and photo task header', async () => {
|
it('renders the quick jump chips and photo task header', async () => {
|
||||||
render(<MobileEventTasksPage />);
|
render(<MobileEventTasksPage />);
|
||||||
|
|
||||||
expect(await screen.findByText('Photo tasks for this event')).toBeInTheDocument();
|
expect(await screen.findByText('Photo task mode')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Quick jump')).toBeInTheDocument();
|
expect(screen.getByText('Quick jump')).toBeInTheDocument();
|
||||||
expect(screen.getByText('assigned')).toBeInTheDocument();
|
expect(screen.getByText('assigned')).toBeInTheDocument();
|
||||||
expect(screen.getByPlaceholderText('Search photo tasks')).toBeInTheDocument();
|
expect(screen.getByPlaceholderText('Search photo tasks')).toBeInTheDocument();
|
||||||
@@ -289,8 +289,8 @@ describe('MobileEventTasksPage', () => {
|
|||||||
it('toggles task details in the hero section', async () => {
|
it('toggles task details in the hero section', async () => {
|
||||||
render(<MobileEventTasksPage />);
|
render(<MobileEventTasksPage />);
|
||||||
|
|
||||||
const detailsLabel = 'Give guests optional photo tasks and prompts.';
|
const detailsLabel = 'Control whether guests see mission cards and prompts.';
|
||||||
expect(await screen.findByText('Photo tasks for this event')).toBeInTheDocument();
|
expect(await screen.findByText('Photo task mode')).toBeInTheDocument();
|
||||||
expect(screen.queryByText(detailsLabel)).not.toBeInTheDocument();
|
expect(screen.queryByText(detailsLabel)).not.toBeInTheDocument();
|
||||||
|
|
||||||
fireEvent.click(screen.getByLabelText(detailsLabel));
|
fireEvent.click(screen.getByLabelText(detailsLabel));
|
||||||
|
|||||||
Reference in New Issue
Block a user