feat: add generating image page, artwork, and map translation

* feat: add options/map flow, dev seed, and artwork fixes

Options page, Kakao map with florist order message, dev tooling, and
create/message dummy gating — without secrets in .env.example.

Co-authored-by: Cursor <cursoragent@cursor.com>

* with generating page + art work

---------

Co-authored-by: 이지은 <ijieun@ijieun-ui-MacBookPro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Chaewon Lee
2026-06-14 09:43:35 +09:00
committed by GitHub
parent 921dfd55f4
commit 80b84bd2ed
25 changed files with 851 additions and 110 deletions

View File

@@ -1,20 +1,49 @@
<script>
/** @typedef {{ text: string, highlight: boolean }} OrderMessageSegment */
let {
plainText = '',
segments = /** @type {OrderMessageSegment[]} */ ([])
enPlainText = '',
koPlainText = ''
} = $props();
/** @type {'ko' | 'en'} */
let activeLang = $state('ko');
let textEn = $state('');
let textKo = $state('');
let seeded = $state(false);
let copied = $state(false);
const hasMessage = $derived(Boolean(plainText?.trim()));
$effect(() => {
if (!seeded && (enPlainText || koPlainText)) {
textEn = enPlainText;
textKo = koPlainText;
seeded = true;
}
});
const activeText = $derived(activeLang === 'ko' ? textKo : textEn);
const hasMessage = $derived(
Boolean(activeText?.trim()) || Boolean(textEn?.trim()) || Boolean(textKo?.trim())
);
/** @param {Event & { currentTarget: HTMLTextAreaElement }} event */
function handleInput(event) {
const value = event.currentTarget.value;
if (activeLang === 'ko') {
textKo = value;
} else {
textEn = value;
}
}
/** @param {'ko' | 'en'} lang */
function setLanguage(lang) {
activeLang = lang;
}
async function handleCopy() {
if (!hasMessage) return;
if (!activeText.trim()) return;
try {
await navigator.clipboard.writeText(plainText);
await navigator.clipboard.writeText(activeText);
copied = true;
setTimeout(() => {
copied = false;
@@ -25,29 +54,50 @@
}
</script>
<div class="flex items-start justify-between gap-3">
<div class="flex items-start gap-3">
{#if hasMessage}
<p class="min-w-0 flex-1 text-sm leading-relaxed text-muted">
{#each segments as segment, index (index)}
{#if segment.highlight}
<span class="text-pill">{'{'}</span><span class="font-medium text-ink"
>{segment.text}</span
><span class="text-pill">{'}'}</span>
{:else}
{segment.text}
{/if}
{/each}
</p>
<textarea
class="min-h-[5.5rem] min-w-0 flex-1 resize-y rounded border border-line bg-transparent px-3 py-2 text-sm leading-relaxed text-muted focus:border-line-strong focus:outline-none"
rows={4}
value={activeText}
oninput={handleInput}
aria-label={activeLang === 'ko' ? '꽃집 주문 멘트 (한국어)' : 'Florist order message (English)'}
></textarea>
{:else}
<p class="text-sm text-muted">Complete the flow to generate your order message.</p>
<p class="min-w-0 flex-1 text-sm text-muted">Complete the flow to generate your order message.</p>
{/if}
<button
type="button"
disabled={!hasMessage}
onclick={handleCopy}
class="shrink-0 rounded bg-pill px-3 py-1.5 text-xs text-surface disabled:opacity-40"
>
{copied ? 'Copied!' : 'Copy'}
</button>
<div class="flex shrink-0 flex-col items-stretch gap-2">
<button
type="button"
disabled={!hasMessage}
onclick={handleCopy}
class="rounded bg-pill px-3 py-1.5 text-xs text-surface disabled:opacity-40"
>
{copied ? 'Copied!' : 'Copy'}
</button>
<div class="flex gap-1">
<button
type="button"
disabled={!hasMessage}
onclick={() => setLanguage('ko')}
class="flex-1 rounded border px-2 py-1.5 text-xs disabled:opacity-40 {activeLang === 'ko'
? 'border-pill bg-pill text-surface'
: 'border-line text-muted hover:border-line-strong'}"
>
Kor
</button>
<button
type="button"
disabled={!hasMessage}
onclick={() => setLanguage('en')}
class="flex-1 rounded border px-2 py-1.5 text-xs disabled:opacity-40 {activeLang === 'en'
? 'border-pill bg-pill text-surface'
: 'border-line text-muted hover:border-line-strong'}"
>
Eng
</button>
</div>
</div>
</div>

View File

@@ -11,7 +11,7 @@
mock = false,
fitBounds = false,
orderPlainText = '',
orderSegments = [],
orderKoPlainText = '',
onrefresh
} = $props();
@@ -53,7 +53,7 @@
</header>
<div class="shrink-0 px-6 pb-4 md:px-10 lg:px-12">
<FloristOrderMessage plainText={orderPlainText} segments={orderSegments} />
<FloristOrderMessage enPlainText={orderPlainText} koPlainText={orderKoPlainText} />
</div>
{#if error}