diff --git a/resources/js/admin/mobile/EventControlRoomPage.tsx b/resources/js/admin/mobile/EventControlRoomPage.tsx index a24396b..0a313f0 100644 --- a/resources/js/admin/mobile/EventControlRoomPage.tsx +++ b/resources/js/admin/mobile/EventControlRoomPage.tsx @@ -93,6 +93,8 @@ type PhotoGridAction = { icon: React.ComponentType<{ size?: number; color?: string }>; onPress: () => void; disabled?: boolean; + backgroundColor?: string; + iconColor?: string; }; function PhotoGrid({ @@ -108,8 +110,8 @@ function PhotoGrid({ }) { const gridStyle: React.CSSProperties = { display: 'grid', - gridTemplateColumns: 'repeat(auto-fill, minmax(120px, 1fr))', - gap: 10, + gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))', + gap: 12, }; return ( @@ -139,8 +141,8 @@ function PhotoGridTile({ isBusy: boolean; }) { const { border, muted, surfaceMuted } = useAdminTheme(); - const overlayBg = withAlpha('#0f172a', 0.65); - const actionBg = withAlpha('#ffffff', 0.14); + const overlayBg = withAlpha('#0f172a', 0.55); + const actionBg = withAlpha('#0f172a', 0.55); return (
{actions.map((action) => ( ))} @@ -207,32 +211,32 @@ function PhotoActionButton({ onPress, disabled = false, backgroundColor, + iconColor, }: { label: string; icon: React.ComponentType<{ size?: number; color?: string }>; onPress: () => void; disabled?: boolean; backgroundColor: string; + iconColor: string; }) { return ( - - - {label} - + ); @@ -258,7 +262,7 @@ export default function MobileEventControlRoomPage() { const isMember = user?.role === 'member'; const slug = slugParam ?? activeEvent?.slug ?? null; const online = useOnlineStatus(); - const { textStrong, text, muted, border, accentSoft, accent, danger } = useAdminTheme(); + const { textStrong, text, muted, border, accentSoft, accent, danger, primary } = useAdminTheme(); const [activeTab, setActiveTab] = React.useState<'moderation' | 'live'>('moderation'); const [moderationPhotos, setModerationPhotos] = React.useState([]); @@ -903,6 +907,9 @@ export default function MobileEventControlRoomPage() { const featureLabel = photo.is_featured ? t('photos.actions.unfeature', 'Remove highlight') : t('photos.actions.feature', 'Set highlight'); + const approveBg = withAlpha(primary, 0.78); + const hideBg = withAlpha(danger, 0.75); + const highlightBg = photo.is_featured ? withAlpha(accent, 0.85) : withAlpha(accent, 0.55); return [ { key: 'approve', @@ -910,6 +917,7 @@ export default function MobileEventControlRoomPage() { icon: Check, onPress: () => handleModerationAction('approve', photo), disabled: !canApprove || isBusy, + backgroundColor: approveBg, }, { key: 'visibility', @@ -917,6 +925,7 @@ export default function MobileEventControlRoomPage() { icon: canShow ? Eye : EyeOff, onPress: () => handleModerationAction(visibilityAction, photo), disabled: isBusy, + backgroundColor: hideBg, }, { key: 'feature', @@ -924,6 +933,7 @@ export default function MobileEventControlRoomPage() { icon: Sparkles, onPress: () => handleModerationAction(featureAction, photo), disabled: isBusy, + backgroundColor: highlightBg, }, ]; }} @@ -1023,6 +1033,9 @@ export default function MobileEventControlRoomPage() { ? t('photos.actions.unfeature', 'Remove highlight') : t('photos.actions.feature', 'Set highlight'); + const approveBg = withAlpha(primary, 0.78); + const hideBg = withAlpha(danger, 0.75); + const highlightBg = photo.is_featured ? withAlpha(accent, 0.85) : withAlpha(accent, 0.55); return [ { key: 'approve', @@ -1038,6 +1051,7 @@ export default function MobileEventControlRoomPage() { } }, disabled: approveDisabled, + backgroundColor: approveBg, }, { key: 'visibility', @@ -1051,6 +1065,7 @@ export default function MobileEventControlRoomPage() { void handleReject(photo); }, disabled: !online || isLiveBusy || isModerationBusy, + backgroundColor: hideBg, }, { key: 'feature', @@ -1058,6 +1073,7 @@ export default function MobileEventControlRoomPage() { icon: Sparkles, onPress: () => handleModerationAction(featureAction, photo), disabled: isModerationBusy, + backgroundColor: highlightBg, }, ]; }} diff --git a/resources/js/admin/mobile/__tests__/EventControlRoomPage.test.tsx b/resources/js/admin/mobile/__tests__/EventControlRoomPage.test.tsx index d6b5e5b..bc83ce5 100644 --- a/resources/js/admin/mobile/__tests__/EventControlRoomPage.test.tsx +++ b/resources/js/admin/mobile/__tests__/EventControlRoomPage.test.tsx @@ -99,8 +99,16 @@ vi.mock('@tamagui/text', () => ({ })); vi.mock('@tamagui/react-native-web-lite', () => ({ - Pressable: ({ children, onPress }: { children: React.ReactNode; onPress?: () => void }) => ( - ), @@ -114,6 +122,7 @@ vi.mock('../theme', () => ({ border: '#e5e7eb', accentSoft: '#eef2ff', accent: '#6366f1', + primary: '#ff5a5f', danger: '#dc2626', surfaceMuted: '#f9fafb', }), @@ -172,8 +181,8 @@ describe('MobileEventControlRoomPage', () => { it('renders compact grid actions for moderation photos', async () => { render(); - expect(await screen.findByText('Approve')).toBeInTheDocument(); - expect(screen.getByText('Hide')).toBeInTheDocument(); - expect(screen.getByText('Set highlight')).toBeInTheDocument(); + expect(await screen.findByLabelText('Approve')).toBeInTheDocument(); + expect(screen.getByLabelText('Hide')).toBeInTheDocument(); + expect(screen.getByLabelText('Set highlight')).toBeInTheDocument(); }); });