Remove sparkbooth option from photobooth UI
This commit is contained in:
@@ -1168,15 +1168,20 @@
|
||||
"mode": "Modus"
|
||||
},
|
||||
"mode": {
|
||||
"title": "Photobooth-Typ auswählen",
|
||||
"description": "Wähle zwischen klassischem FTP und Sparkbooth HTTP-Upload. Umschalten generiert neue Zugangsdaten.",
|
||||
"active": "Aktuell: {{mode}}"
|
||||
"title": "Uploader-Verbindung",
|
||||
"description": "Nutze die Fotospiel-Uploader-App für HTTP-Uploads. Beim Zurücksetzen werden neue Zugangsdaten generiert.",
|
||||
"active": "Aktuell: {{mode}}",
|
||||
"uploader": "Uploader-App (HTTP)"
|
||||
},
|
||||
"selector": {
|
||||
"title": "Verbindung",
|
||||
"description": "Nutze die Fotospiel-Uploader-App für HTTP-Uploads."
|
||||
},
|
||||
"credentials": {
|
||||
"heading": "FTP-Zugangsdaten",
|
||||
"description": "Teile die Zugangsdaten mit eurer Photobooth-Software.",
|
||||
"sparkboothTitle": "Uploader-App (HTTP)",
|
||||
"sparkboothDescription": "Trage URL, Benutzername und Passwort in die Fotospiel-Uploader-App ein. Antworten sind JSON (optional XML).",
|
||||
"heading": "Zugangsdaten für die Uploader-App",
|
||||
"description": "Teile die Zugangsdaten mit der Fotospiel-Uploader-App.",
|
||||
"uploaderTitle": "Uploader-App (HTTP)",
|
||||
"uploaderDescription": "Trage URL, Benutzername und Passwort in die Fotospiel-Uploader-App ein. Antworten sind JSON (optional XML).",
|
||||
"host": "Host",
|
||||
"port": "Port",
|
||||
"username": "Benutzername",
|
||||
@@ -1197,6 +1202,10 @@
|
||||
"failed": "Verbindungscode konnte nicht erstellt werden."
|
||||
}
|
||||
},
|
||||
"uploader": {
|
||||
"format": "Antwort-Format",
|
||||
"hint": "POST mit Mediendatei oder base64-Feld \"media\"; die App nutzt diese Zugangsdaten."
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Photobooth aktivieren",
|
||||
"disable": "Deaktivieren",
|
||||
@@ -1214,9 +1223,9 @@
|
||||
"title": "Setup-Checkliste",
|
||||
"description": "Durchlaufe die Schritte, bevor du Gästen Zugang gibst.",
|
||||
"enable": "Zugang aktivieren",
|
||||
"enableCopy": "Aktiviere den FTP-Account für eure Photobooth-Software.",
|
||||
"enableCopy": "Aktiviere die Verbindung für die Uploader-App.",
|
||||
"share": "Zugang teilen",
|
||||
"shareCopy": "Übergib Host, Benutzer & Passwort an den Betreiber.",
|
||||
"shareCopy": "Übergib URL, Benutzername & Passwort an den Betreiber.",
|
||||
"monitor": "Uploads beobachten",
|
||||
"monitorCopy": "Verfolge Uploads & Limits direkt im Dashboard."
|
||||
},
|
||||
@@ -1443,7 +1452,7 @@
|
||||
"photobooth": {
|
||||
"title": "Fotobox-Uploads",
|
||||
"titleForEvent": "Fotobox-Uploads verwalten",
|
||||
"subtitle": "Erstelle FTP-Zugänge für Photobooth-Software und behalte Limits im Blick.",
|
||||
"subtitle": "Erstelle Zugang für die Uploader-App und behalte Limits im Blick.",
|
||||
"actions": {
|
||||
"backToEvent": "Zur Detailansicht",
|
||||
"allEvents": "Zur Eventliste"
|
||||
|
||||
@@ -881,15 +881,20 @@
|
||||
"mode": "Mode"
|
||||
},
|
||||
"mode": {
|
||||
"title": "Choose your photobooth type",
|
||||
"description": "Pick classic FTP or Sparkbooth HTTP upload. Switching regenerates credentials.",
|
||||
"active": "Current: {{mode}}"
|
||||
"title": "Uploader connection",
|
||||
"description": "Use the Fotospiel uploader app for live HTTP uploads. Rotating access regenerates credentials.",
|
||||
"active": "Current: {{mode}}",
|
||||
"uploader": "Uploader App (HTTP)"
|
||||
},
|
||||
"selector": {
|
||||
"title": "Connection",
|
||||
"description": "Use the Fotospiel uploader app for HTTP uploads."
|
||||
},
|
||||
"credentials": {
|
||||
"heading": "FTP credentials",
|
||||
"description": "Share these credentials with your photobooth software.",
|
||||
"sparkboothTitle": "Uploader App (HTTP)",
|
||||
"sparkboothDescription": "Enter URL, username and password in the Fotospiel uploader app. Responses default to JSON (XML optional).",
|
||||
"heading": "Uploader app credentials",
|
||||
"description": "Share these credentials with the Fotospiel uploader app.",
|
||||
"uploaderTitle": "Uploader App (HTTP)",
|
||||
"uploaderDescription": "Enter URL, username and password in the Fotospiel uploader app. Responses default to JSON (XML optional).",
|
||||
"host": "Host",
|
||||
"port": "Port",
|
||||
"username": "Username",
|
||||
@@ -910,6 +915,10 @@
|
||||
"failed": "Connect code could not be created."
|
||||
}
|
||||
},
|
||||
"uploader": {
|
||||
"format": "Response format",
|
||||
"hint": "POST with media file or base64 \"media\" field; app uses these credentials."
|
||||
},
|
||||
"actions": {
|
||||
"enable": "Activate photobooth",
|
||||
"disable": "Disable",
|
||||
@@ -927,9 +936,9 @@
|
||||
"title": "Setup checklist",
|
||||
"description": "Complete each step before guests upload.",
|
||||
"enable": "Activate access",
|
||||
"enableCopy": "Enable the FTP account in your photobooth software.",
|
||||
"enableCopy": "Enable the uploader app connection for this event.",
|
||||
"share": "Share credentials",
|
||||
"shareCopy": "Hand over host, user, and password to the operator.",
|
||||
"shareCopy": "Share URL, username, and password with the operator.",
|
||||
"monitor": "Monitor uploads",
|
||||
"monitorCopy": "Watch uploads & limits in the dashboard."
|
||||
},
|
||||
@@ -1436,11 +1445,11 @@
|
||||
"submit": "Save emotion"
|
||||
}
|
||||
},
|
||||
"management": {
|
||||
"photobooth": {
|
||||
"title": "Photobooth uploads",
|
||||
"titleForEvent": "Manage photobooth uploads",
|
||||
"subtitle": "Create FTP access for photobooth software and keep limits in sight.",
|
||||
"management": {
|
||||
"photobooth": {
|
||||
"title": "Photobooth uploads",
|
||||
"titleForEvent": "Manage photobooth uploads",
|
||||
"subtitle": "Create uploader access for photobooth apps and keep limits in sight.",
|
||||
"actions": {
|
||||
"backToEvent": "Back to detail view",
|
||||
"allEvents": "Back to event list"
|
||||
|
||||
@@ -35,7 +35,6 @@ export default function MobileEventPhotoboothPage() {
|
||||
|
||||
const [event, setEvent] = React.useState<TenantEvent | null>(null);
|
||||
const [status, setStatus] = React.useState<PhotoboothStatus | null>(null);
|
||||
const [selectedMode, setSelectedMode] = React.useState<'ftp' | 'sparkbooth'>('ftp');
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [updating, setUpdating] = React.useState(false);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
@@ -54,7 +53,6 @@ export default function MobileEventPhotoboothPage() {
|
||||
const [eventData, statusData] = await Promise.all([getEvent(slug), getEventPhotoboothStatus(slug)]);
|
||||
setEvent(eventData);
|
||||
setStatus(statusData);
|
||||
setSelectedMode(statusData.mode ?? 'ftp');
|
||||
} catch (err) {
|
||||
if (!isAuthError(err)) {
|
||||
setError(getApiErrorMessage(err, t('management.photobooth.errors.loadFailed', 'Photobooth-Link konnte nicht geladen werden.')));
|
||||
@@ -68,20 +66,14 @@ export default function MobileEventPhotoboothPage() {
|
||||
void load();
|
||||
}, [load]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (status?.mode) {
|
||||
setSelectedMode(status.mode);
|
||||
}
|
||||
}, [status?.mode]);
|
||||
|
||||
const handleEnable = async (mode?: 'ftp' | 'sparkbooth') => {
|
||||
const handleEnable = async () => {
|
||||
if (!slug) return;
|
||||
const nextMode = mode ?? selectedMode ?? status?.mode ?? 'ftp';
|
||||
const nextMode = 'sparkbooth';
|
||||
setUpdating(true);
|
||||
try {
|
||||
const result = await enableEventPhotobooth(slug, { mode: nextMode });
|
||||
setStatus(result);
|
||||
setSelectedMode(result.mode ?? nextMode);
|
||||
toast.success(t('management.photobooth.actions.enable', 'Zugang aktiviert'));
|
||||
} catch (err) {
|
||||
if (!isAuthError(err)) {
|
||||
@@ -94,12 +86,11 @@ export default function MobileEventPhotoboothPage() {
|
||||
|
||||
const handleDisable = async () => {
|
||||
if (!slug) return;
|
||||
const mode = status?.mode ?? selectedMode ?? 'ftp';
|
||||
const mode = 'sparkbooth';
|
||||
setUpdating(true);
|
||||
try {
|
||||
const result = await disableEventPhotobooth(slug, { mode });
|
||||
setStatus(result);
|
||||
setSelectedMode(result.mode ?? mode);
|
||||
toast.success(t('management.photobooth.actions.disable', 'Zugang deaktiviert'));
|
||||
} catch (err) {
|
||||
if (!isAuthError(err)) {
|
||||
@@ -112,12 +103,11 @@ export default function MobileEventPhotoboothPage() {
|
||||
|
||||
const handleRotate = async () => {
|
||||
if (!slug) return;
|
||||
const mode = selectedMode ?? status?.mode ?? 'ftp';
|
||||
const mode = 'sparkbooth';
|
||||
setUpdating(true);
|
||||
try {
|
||||
const result = await rotateEventPhotobooth(slug, { mode });
|
||||
setStatus(result);
|
||||
setSelectedMode(result.mode ?? mode);
|
||||
toast.success(t('management.photobooth.presets.actions.rotate', 'Zugang zurückgesetzt'));
|
||||
} catch (err) {
|
||||
if (!isAuthError(err)) {
|
||||
@@ -147,26 +137,18 @@ export default function MobileEventPhotoboothPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const activeMode = selectedMode ?? status?.mode ?? 'ftp';
|
||||
const isSpark = activeMode === 'sparkbooth';
|
||||
const spark = status?.sparkbooth ?? null;
|
||||
const ftp = status?.ftp ?? null;
|
||||
const metrics = isSpark ? spark?.metrics ?? null : status?.metrics ?? null;
|
||||
const expiresAt = isSpark ? spark?.expires_at ?? status?.expires_at : status?.expires_at ?? spark?.expires_at;
|
||||
const metrics = spark?.metrics ?? null;
|
||||
const expiresAt = spark?.expires_at ?? status?.expires_at;
|
||||
const lastUploadAt = metrics?.last_upload_at;
|
||||
const uploads24h = metrics?.uploads_24h ?? metrics?.uploads_today;
|
||||
const uploadsTotal = metrics?.uploads_total;
|
||||
const connectionPath = status?.path ?? '—';
|
||||
const ftpUrl = status?.ftp_url ?? '—';
|
||||
const uploadUrl = isSpark ? spark?.upload_url ?? status?.upload_url : null;
|
||||
const uploadUrl = spark?.upload_url ?? status?.upload_url;
|
||||
const responseFormat = spark?.response_format ?? 'json';
|
||||
const username = isSpark ? spark?.username ?? status?.username : status?.username ?? spark?.username ?? null;
|
||||
const password = isSpark ? spark?.password ?? status?.password : status?.password ?? spark?.password ?? null;
|
||||
const username = spark?.username ?? status?.username ?? null;
|
||||
const password = spark?.password ?? status?.password ?? null;
|
||||
|
||||
const modeLabel =
|
||||
activeMode === 'sparkbooth'
|
||||
? t('photobooth.credentials.sparkboothTitle', 'Uploader App (HTTP)')
|
||||
: t('photobooth.credentials.heading', 'FTP (Classic)');
|
||||
const modeLabel = t('photobooth.mode.uploader', 'Uploader App (HTTP)');
|
||||
|
||||
const isActive = Boolean(status?.enabled);
|
||||
const title = t('photobooth.title', 'Photobooth');
|
||||
@@ -174,7 +156,7 @@ export default function MobileEventPhotoboothPage() {
|
||||
const handleToggle = (checked: boolean) => {
|
||||
if (!slug || updating) return;
|
||||
if (checked) {
|
||||
void handleEnable(status?.mode ?? 'ftp');
|
||||
void handleEnable();
|
||||
} else {
|
||||
void handleDisable();
|
||||
}
|
||||
@@ -262,93 +244,53 @@ export default function MobileEventPhotoboothPage() {
|
||||
|
||||
<MobileCard space="$2">
|
||||
<Text fontSize="$sm" fontWeight="700" color={text}>
|
||||
{t('photobooth.selector.title', 'Choose adapter')}
|
||||
{t('photobooth.selector.title', 'Connection')}
|
||||
</Text>
|
||||
<Text fontSize="$xs" color={muted}>
|
||||
{t(
|
||||
'photobooth.selector.description',
|
||||
'FTP (Classic) works with most booths. The Uploader App uses HTTP POST without FTP.'
|
||||
)}
|
||||
{t('photobooth.selector.description', 'Use the Fotospiel uploader app for HTTP uploads.')}
|
||||
</Text>
|
||||
<XStack space="$2" marginTop="$2" flexWrap="nowrap">
|
||||
<XStack flex={1} minWidth={0}>
|
||||
<CTAButton
|
||||
label={t('photobooth.mode.ftp', 'FTP (Classic)')}
|
||||
tone={activeMode === 'ftp' ? 'primary' : 'ghost'}
|
||||
onPress={() => setSelectedMode('ftp')}
|
||||
disabled={updating}
|
||||
style={{ width: '100%', paddingHorizontal: 10, paddingVertical: 10 }}
|
||||
/>
|
||||
</XStack>
|
||||
<XStack flex={1} minWidth={0}>
|
||||
<CTAButton
|
||||
label={t('photobooth.mode.sparkbooth', 'Uploader App (HTTP)')}
|
||||
tone={activeMode === 'sparkbooth' ? 'primary' : 'ghost'}
|
||||
onPress={() => setSelectedMode('sparkbooth')}
|
||||
disabled={updating}
|
||||
style={{ width: '100%', paddingHorizontal: 10, paddingVertical: 10 }}
|
||||
/>
|
||||
</XStack>
|
||||
</XStack>
|
||||
</MobileCard>
|
||||
|
||||
<MobileCard space="$2">
|
||||
<XStack alignItems="center" justifyContent="space-between">
|
||||
<Text fontSize="$sm" fontWeight="700" color={text}>
|
||||
{isSpark ? t('photobooth.credentials.sparkboothTitle', 'Uploader App (HTTP)') : t('photobooth.credentials.heading', 'FTP credentials')}
|
||||
{t('photobooth.credentials.uploaderTitle', 'Uploader App (HTTP)')}
|
||||
</Text>
|
||||
{!isSpark && ftp?.require_ftps ? <PillBadge tone="warning">{t('photobooth.credentials.ftps', 'FTPS required')}</PillBadge> : null}
|
||||
</XStack>
|
||||
<YStack space="$1">
|
||||
{isSpark ? (
|
||||
<>
|
||||
<CredentialRow label={t('photobooth.credentials.postUrl', 'Upload URL')} value={uploadUrl ?? '—'} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.username', 'Username')} value={username ?? '—'} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.password', 'Password')} value={password ?? '—'} border={border} masked />
|
||||
<CredentialRow label={t('photobooth.sparkbooth.format', 'Response format')} value={responseFormat.toUpperCase()} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.postUrl', 'Upload URL')} value={uploadUrl ?? '—'} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.username', 'Username')} value={username ?? '—'} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.password', 'Password')} value={password ?? '—'} border={border} masked />
|
||||
<CredentialRow label={t('photobooth.uploader.format', 'Response format')} value={responseFormat.toUpperCase()} border={border} />
|
||||
<Text fontSize="$xs" color={muted}>
|
||||
{t('photobooth.uploader.hint', 'POST with media file or base64 "media" field; app uses these credentials.')}
|
||||
</Text>
|
||||
<YStack space="$2" marginTop="$2">
|
||||
<Text fontSize="$xs" color={muted}>
|
||||
{t('photobooth.connectCode.description', 'Create a 6-digit code for the uploader app.')}
|
||||
</Text>
|
||||
<CTAButton
|
||||
label={
|
||||
connectLoading
|
||||
? t('common.processing', '...')
|
||||
: t('photobooth.connectCode.actions.generate', 'Generate connect code')
|
||||
}
|
||||
onPress={handleGenerateConnectCode}
|
||||
iconLeft={<PlugZap size={14} color={surface} />}
|
||||
disabled={!isActive || updating || connectLoading}
|
||||
style={{ width: '100%', paddingHorizontal: 10, paddingVertical: 10 }}
|
||||
/>
|
||||
{connectCode ? (
|
||||
<CredentialRow label={t('photobooth.connectCode.label', 'Connect code')} value={connectCode} border={border} />
|
||||
) : null}
|
||||
{connectExpiresAt ? (
|
||||
<Text fontSize="$xs" color={muted}>
|
||||
{t('photobooth.sparkbooth.hint', 'POST with media file or base64 "media" field; app uses these credentials.')}
|
||||
{t('photobooth.connectCode.expires', 'Expires: {{date}}', {
|
||||
date: formatEventDate(connectExpiresAt, locale),
|
||||
})}
|
||||
</Text>
|
||||
<YStack space="$2" marginTop="$2">
|
||||
<Text fontSize="$xs" color={muted}>
|
||||
{t('photobooth.connectCode.description', 'Create a 6-digit code for the uploader app.')}
|
||||
</Text>
|
||||
<CTAButton
|
||||
label={
|
||||
connectLoading
|
||||
? t('common.processing', '...')
|
||||
: t('photobooth.connectCode.actions.generate', 'Generate connect code')
|
||||
}
|
||||
onPress={handleGenerateConnectCode}
|
||||
iconLeft={<PlugZap size={14} color={surface} />}
|
||||
disabled={!isActive || updating || connectLoading}
|
||||
style={{ width: '100%', paddingHorizontal: 10, paddingVertical: 10 }}
|
||||
/>
|
||||
{connectCode ? (
|
||||
<CredentialRow label={t('photobooth.connectCode.label', 'Connect code')} value={connectCode} border={border} />
|
||||
) : null}
|
||||
{connectExpiresAt ? (
|
||||
<Text fontSize="$xs" color={muted}>
|
||||
{t('photobooth.connectCode.expires', 'Expires: {{date}}', {
|
||||
date: formatEventDate(connectExpiresAt, locale),
|
||||
})}
|
||||
</Text>
|
||||
) : null}
|
||||
</YStack>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CredentialRow label={t('photobooth.credentials.host', 'Host')} value={ftp?.host ?? '—'} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.port', 'Port')} value={String(ftp?.port ?? '—')} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.path', 'Target folder')} value={connectionPath} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.postUrl', 'FTP URL')} value={ftpUrl} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.username', 'Username')} value={username ?? '—'} border={border} />
|
||||
<CredentialRow label={t('photobooth.credentials.password', 'Password')} value={password ?? '—'} border={border} masked />
|
||||
<Text fontSize="$xs" color={muted}>
|
||||
{t('photobooth.credentials.ftpsHint', 'Use FTPS if required; uploads go into the target folder for this event.')}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
) : null}
|
||||
</YStack>
|
||||
</YStack>
|
||||
<XStack space="$2" marginTop="$2" flexWrap="wrap">
|
||||
<XStack flex={1} minWidth={0}>
|
||||
@@ -363,7 +305,7 @@ export default function MobileEventPhotoboothPage() {
|
||||
<XStack flex={1} minWidth={0}>
|
||||
<CTAButton
|
||||
label={isActive ? t('photobooth.actions.disable', 'Disable uploads') : t('photobooth.actions.enable', 'Enable uploads')}
|
||||
onPress={() => (isActive ? handleDisable() : handleEnable(selectedMode))}
|
||||
onPress={() => (isActive ? handleDisable() : handleEnable())}
|
||||
tone={isActive ? 'ghost' : 'primary'}
|
||||
iconLeft={isActive ? <Power size={14} color={text} /> : <PlugZap size={14} color={surface} />}
|
||||
disabled={updating}
|
||||
|
||||
Reference in New Issue
Block a user