Uncommit feature in character creation

Players can now unlock and revise any reasonably revisable choice while
character creation is ongoing: basic Rat Records (also in recruit
creation), submitted techniques (until the swap phase begins), J/Q/K
face-card assignments (until everyone is ready), and Like/Hate answers
written for crewmates. New endpoints unsubmit-techniques and
unassign-face-techniques clear the locked-in state server-side so the
phase machine waits for the revision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 17:05:52 -07:00
parent ba32c96b7b
commit 952b1be872
6 changed files with 224 additions and 14 deletions

View File

@@ -32,11 +32,13 @@
good_at_math: state.player.good_at_math || ''
};
let savingBasic = false;
let editingBasic = false;
async function saveBasicDetails() {
savingBasic = true;
try {
await apiRequest(`/game/${state.game.id}/player/${me.id}/save-basic`, 'POST', basicDetails);
editingBasic = false;
} catch(e) {
console.error(e);
} finally {
@@ -44,6 +46,16 @@
}
}
function reviseBasicDetails() {
basicDetails = {
avatar_look: me.avatar_look || '',
avatar_smell: me.avatar_smell || '',
first_words: me.first_words || '',
good_at_math: me.good_at_math || ''
};
editingBasic = true;
}
$: basicComplete = !!(me.avatar_look && me.avatar_smell && me.first_words && me.good_at_math);
$: likeDone = !me.other_like_from_player_id || !!me.other_like;
$: hateDone = !me.other_hate_from_player_id || !!me.other_hate;
@@ -113,8 +125,8 @@
// My outstanding tasks for other recruits
$: myTasks = recruits.filter(p => p.id !== me.id).map(p => ({
recruit: p,
like: p.other_like_from_player_id === me.id && !p.other_like,
hate: p.other_hate_from_player_id === me.id && !p.other_hate,
like: p.other_like_from_player_id === me.id,
hate: p.other_hate_from_player_id === me.id,
techSlots: incomingTechs(p).map((s, i) => ({ ...s, slot: i })).filter(s => s.from_id === me.id)
})).filter(t => t.like || t.hate || t.techSlots.length > 0);
@@ -141,13 +153,14 @@
<!-- MY NEW RECRUIT SHEET -->
<div class="card glass-panel section-basic">
<h3>I. Your New Rat Records {basicComplete ? '✅' : '❌'}</h3>
{#if basicComplete}
{#if basicComplete && !editingBasic}
<div class="read-only-sheet">
<div class="record-line"><strong>Look:</strong> {me.avatar_look}</div>
<div class="record-line"><strong>Smell:</strong> {me.avatar_smell}</div>
<div class="record-line"><strong>First Words:</strong> "{me.first_words}"</div>
<div class="record-line"><strong>Good at Math?</strong> {me.good_at_math}</div>
</div>
<button type="button" class="btn btn-secondary btn-small mt-4" on:click={reviseBasicDetails}>✏️ Revise Records</button>
{:else}
<form on:submit|preventDefault={saveBasicDetails} class="creation-form">
<div class="form-group">
@@ -245,7 +258,10 @@
{#each myTasks as task (task.recruit.id)}
{#if task.like}
<div class="inbox-item">
<label>What do you LIKE about {displayName(task.recruit)}?</label>
<label>
What do you LIKE about {displayName(task.recruit)}?
{#if task.recruit.other_like}<span class="text-success">(submitted: "{task.recruit.other_like}" — you can revise it)</span>{/if}
</label>
<div class="input-row">
<input type="text" class="input-field" bind:value={inboxAnswers[`${task.recruit.id}:like`]} placeholder="e.g. They always share their cheese"/>
{#if devMode}<button type="button" class="btn btn-secondary btn-small" on:click={() => inboxAnswers[`${task.recruit.id}:like`] = getSuggestion('like')}>Suggest</button>{/if}
@@ -255,7 +271,10 @@
{/if}
{#if task.hate}
<div class="inbox-item">
<label>What do you HATE about {displayName(task.recruit)}?</label>
<label>
What do you HATE about {displayName(task.recruit)}?
{#if task.recruit.other_hate}<span class="text-success">(submitted: "{task.recruit.other_hate}" — you can revise it)</span>{/if}
</label>
<div class="input-row">
<input type="text" class="input-field" bind:value={inboxAnswers[`${task.recruit.id}:hate`]} placeholder="e.g. They snore too loudly"/>
{#if devMode}<button type="button" class="btn btn-secondary btn-small" on:click={() => inboxAnswers[`${task.recruit.id}:hate`] = getSuggestion('hate')}>Suggest</button>{/if}