mirror of
https://github.com/immich-app/static-pages.git
synced 2026-09-30 13:23:05 +08:00
70 lines
2.2 KiB
Svelte
70 lines
2.2 KiB
Svelte
<script lang="ts">
|
|
import { Button } from '@immich/ui';
|
|
import type { SurveyQuestion, SurveyAnswer } from '$lib/types';
|
|
import RadioQuestion from './RadioQuestion.svelte';
|
|
import EmailQuestion from './EmailQuestion.svelte';
|
|
import EmailSignupQuestion from './EmailSignupQuestion.svelte';
|
|
import TextareaQuestion from './TextareaQuestion.svelte';
|
|
|
|
interface Props {
|
|
question: SurveyQuestion;
|
|
answer?: SurveyAnswer;
|
|
onAnswer: (value: string, otherText?: string) => void;
|
|
onNext: () => void;
|
|
onBack: () => void;
|
|
canGoBack: boolean;
|
|
isLast?: boolean;
|
|
}
|
|
|
|
let { question, answer, onAnswer, onNext, onBack, canGoBack, isLast = false }: Props = $props();
|
|
|
|
const hasAnswer = $derived(!!answer?.value);
|
|
const isOptional = $derived(!question.required);
|
|
|
|
let autoNextTimer: ReturnType<typeof setTimeout> | undefined;
|
|
|
|
function handleRadioAnswer(value: string, otherText?: string) {
|
|
onAnswer(value, otherText);
|
|
// Auto-advance on radio pick (but not for "Other" with text input)
|
|
if (value !== 'Other' || !question.hasOther) {
|
|
clearTimeout(autoNextTimer);
|
|
autoNextTimer = setTimeout(() => onNext(), 200);
|
|
}
|
|
}
|
|
|
|
const buttonText = $derived.by(() => {
|
|
if (isLast) {
|
|
return 'Submit';
|
|
}
|
|
|
|
if (hasAnswer || !isOptional) {
|
|
return 'Next';
|
|
}
|
|
|
|
return 'Skip';
|
|
});
|
|
</script>
|
|
|
|
<div class="w-full max-w-[640px] px-4">
|
|
{#if question.type === 'radio'}
|
|
<RadioQuestion {question} {answer} onAnswer={handleRadioAnswer} />
|
|
{:else if question.type === 'email'}
|
|
<EmailQuestion {question} {answer} onAnswer={(v) => onAnswer(v)} />
|
|
{:else if question.type === 'email-signup'}
|
|
<EmailSignupQuestion {question} {answer} {onAnswer} />
|
|
{:else if question.type === 'textarea'}
|
|
<TextareaQuestion {question} {answer} onAnswer={(v) => onAnswer(v)} />
|
|
{/if}
|
|
</div>
|
|
|
|
<div class="fixed bottom-0 left-0 z-40 flex w-full justify-center bg-light px-4 pt-4 pb-6">
|
|
<div class="flex w-full max-w-[640px] items-center gap-3">
|
|
{#if canGoBack}
|
|
<Button variant="outline" onclick={onBack}>Back</Button>
|
|
{/if}
|
|
<Button color="primary" disabled={!hasAnswer && !isOptional} onclick={onNext}>
|
|
{buttonText}
|
|
</Button>
|
|
</div>
|
|
</div>
|