feat(contribution): port join.vue to ContributionAmountField
Replace inline cadence radios, contribution input + presets, guidance label, and billing summary with the shared ContributionAmountField component. Removes duplicated state (guidanceLabel, firstCharge), unused imports (CONTRIBUTION_PRESETS, getGuidanceLabel), and the matching CSS rules. The parent retains the cadence ref because formatContributionAmount (left-column tier list) reads it.
This commit is contained in:
parent
f28558a433
commit
26ee1ca60d
1 changed files with 11 additions and 172 deletions
|
|
@ -129,7 +129,7 @@
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Your name"
|
placeholder="Your name"
|
||||||
required
|
required
|
||||||
/>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="join-email">Email Address</label>
|
<label class="form-label" for="join-email">Email Address</label>
|
||||||
|
|
@ -140,7 +140,7 @@
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="you@example.com"
|
placeholder="you@example.com"
|
||||||
required
|
required
|
||||||
/>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Circle</label>
|
<label class="form-label">Circle</label>
|
||||||
|
|
@ -152,7 +152,7 @@
|
||||||
type="radio"
|
type="radio"
|
||||||
name="circle"
|
name="circle"
|
||||||
value="community"
|
value="community"
|
||||||
/>
|
>
|
||||||
<label for="circle-community">
|
<label for="circle-community">
|
||||||
<span
|
<span
|
||||||
class="circle-label-name"
|
class="circle-label-name"
|
||||||
|
|
@ -169,7 +169,7 @@
|
||||||
type="radio"
|
type="radio"
|
||||||
name="circle"
|
name="circle"
|
||||||
value="founder"
|
value="founder"
|
||||||
/>
|
>
|
||||||
<label for="circle-founder">
|
<label for="circle-founder">
|
||||||
<span
|
<span
|
||||||
class="circle-label-name"
|
class="circle-label-name"
|
||||||
|
|
@ -186,7 +186,7 @@
|
||||||
type="radio"
|
type="radio"
|
||||||
name="circle"
|
name="circle"
|
||||||
value="practitioner"
|
value="practitioner"
|
||||||
/>
|
>
|
||||||
<label for="circle-practitioner">
|
<label for="circle-practitioner">
|
||||||
<span
|
<span
|
||||||
class="circle-label-name"
|
class="circle-label-name"
|
||||||
|
|
@ -198,90 +198,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<ContributionAmountField
|
||||||
<label class="form-label">Billing Cadence</label>
|
v-model="form.contributionAmount"
|
||||||
<div class="cadence-radios">
|
v-model:cadence="cadence"
|
||||||
<div class="circle-radio">
|
/>
|
||||||
<input
|
|
||||||
id="cadence-monthly"
|
|
||||||
v-model="cadence"
|
|
||||||
type="radio"
|
|
||||||
name="cadence"
|
|
||||||
value="monthly"
|
|
||||||
/>
|
|
||||||
<label for="cadence-monthly">
|
|
||||||
<span class="circle-label-name">Per Month</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="circle-radio">
|
|
||||||
<input
|
|
||||||
id="cadence-annual"
|
|
||||||
v-model="cadence"
|
|
||||||
type="radio"
|
|
||||||
name="cadence"
|
|
||||||
value="annual"
|
|
||||||
/>
|
|
||||||
<label for="cadence-annual">
|
|
||||||
<span class="circle-label-name">Per Year</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label" for="join-contribution">
|
|
||||||
Monthly Contribution
|
|
||||||
</label>
|
|
||||||
<div class="contribution-input-row">
|
|
||||||
<span class="contribution-currency">$</span>
|
|
||||||
<input
|
|
||||||
id="join-contribution"
|
|
||||||
v-model.number="form.contributionAmount"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
inputmode="numeric"
|
|
||||||
class="contribution-input"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="contribution-presets"
|
|
||||||
role="group"
|
|
||||||
aria-label="Suggested amounts"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
v-for="preset in CONTRIBUTION_PRESETS"
|
|
||||||
:key="preset.amount"
|
|
||||||
type="button"
|
|
||||||
class="contribution-preset-chip"
|
|
||||||
@click="form.contributionAmount = preset.amount"
|
|
||||||
>
|
|
||||||
${{ preset.amount }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<p v-if="guidanceLabel" class="contribution-guidance">
|
|
||||||
{{ guidanceLabel }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div v-if="form.contributionAmount > 0" class="form-group">
|
|
||||||
<div class="billing-summary">
|
|
||||||
<p class="billing-summary-line">
|
|
||||||
You'll be charged <strong>${{ firstCharge }} today</strong
|
|
||||||
><span v-if="cadence === 'annual'">
|
|
||||||
(${{ form.contributionAmount }}/month × 12)</span
|
|
||||||
>.
|
|
||||||
</p>
|
|
||||||
<p class="billing-summary-line">
|
|
||||||
Then
|
|
||||||
<strong
|
|
||||||
>${{ firstCharge }} every
|
|
||||||
{{ cadence === "annual" ? "year" : "month" }}</strong
|
|
||||||
>, until you cancel.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group full-width">
|
<div class="form-group full-width">
|
||||||
<label class="checkbox-label">
|
<label class="checkbox-label">
|
||||||
<input v-model="form.agreedToGuidelines" type="checkbox" />
|
<input v-model="form.agreedToGuidelines" type="checkbox" >
|
||||||
<span>
|
<span>
|
||||||
I agree to the Ghost Guild
|
I agree to the Ghost Guild
|
||||||
<NuxtLink to="/community-guidelines" target="_blank"
|
<NuxtLink to="/community-guidelines" target="_blank"
|
||||||
|
|
@ -385,11 +308,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref, computed, onMounted, onUnmounted } from "vue";
|
import { reactive, ref, computed, onMounted, onUnmounted } from "vue";
|
||||||
import { getCircleOptions } from "~/config/circles";
|
import { getCircleOptions } from "~/config/circles";
|
||||||
import {
|
import { requiresPayment } from "~/config/contributions";
|
||||||
requiresPayment,
|
|
||||||
CONTRIBUTION_PRESETS,
|
|
||||||
getGuidanceLabel,
|
|
||||||
} from "~/config/contributions";
|
|
||||||
|
|
||||||
useSiteMeta({
|
useSiteMeta({
|
||||||
title: "Join",
|
title: "Join",
|
||||||
|
|
@ -475,13 +394,6 @@ const needsPayment = computed(() => {
|
||||||
return requiresPayment(form.contributionAmount);
|
return requiresPayment(form.contributionAmount);
|
||||||
});
|
});
|
||||||
|
|
||||||
const guidanceLabel = computed(() => getGuidanceLabel(form.contributionAmount));
|
|
||||||
|
|
||||||
const firstCharge = computed(() => {
|
|
||||||
const amount = form.contributionAmount || 0;
|
|
||||||
return cadence.value === "annual" ? amount * 12 : amount;
|
|
||||||
});
|
|
||||||
|
|
||||||
const flowSummary = computed(() => ({
|
const flowSummary = computed(() => ({
|
||||||
name: form.name,
|
name: form.name,
|
||||||
email: form.email,
|
email: form.email,
|
||||||
|
|
@ -840,79 +752,6 @@ onUnmounted(() => {
|
||||||
color: var(--text-faint);
|
color: var(--text-faint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- CADENCE RADIOS ---- */
|
|
||||||
.cadence-radios {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- CONTRIBUTION AMOUNT INPUT + CHIPS ---- */
|
|
||||||
.contribution-input-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
|
||||||
.contribution-currency {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.contribution-input {
|
|
||||||
flex: 1;
|
|
||||||
padding: 0.5rem 0.75rem;
|
|
||||||
background: var(--input-bg);
|
|
||||||
border: 1px solid var(--parch);
|
|
||||||
font-family: "Commit Mono", monospace;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
.contribution-input:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: var(--candle);
|
|
||||||
}
|
|
||||||
.contribution-presets {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.5rem;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
.contribution-preset-chip {
|
|
||||||
padding: 0.25rem 0.75rem;
|
|
||||||
background: transparent;
|
|
||||||
border: 1px dashed var(--parch);
|
|
||||||
font-family: "Commit Mono", monospace;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.contribution-preset-chip:hover {
|
|
||||||
border-style: solid;
|
|
||||||
border-color: var(--candle);
|
|
||||||
}
|
|
||||||
.contribution-guidance {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-style: italic;
|
|
||||||
color: var(--ink-soft, currentColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- BILLING SUMMARY ---- */
|
|
||||||
.billing-summary {
|
|
||||||
padding: 12px 16px;
|
|
||||||
border: 1px dashed var(--border);
|
|
||||||
background: var(--surface);
|
|
||||||
}
|
|
||||||
.billing-summary-line {
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--text);
|
|
||||||
line-height: 1.5;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.billing-summary-line + .billing-summary-line {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
.billing-summary-line strong {
|
|
||||||
color: var(--text-bright);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- CIRCLE RADIOS ---- */
|
/* ---- CIRCLE RADIOS ---- */
|
||||||
.circle-radios {
|
.circle-radios {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue