Rebrand: Co-op Check-in -> Co-op Survey in user-facing copy
Updates the tool product name across the app UI (header, page title, section labels, form buttons, success/error states, report stat labels), README, deployment docs, and the CiviCRM email template guidance. Custom domain references move from check-in.fci.coop to survey.fci.coop (DNS update still required). The underlying CiviCRM "Check-in (organizing)" activity type, custom group machine names (Check_in_data__organizing_), health-check ids, and the internal org_engagement_check_in form id are unchanged -- those are CiviCRM contract surfaces, not product copy.
This commit is contained in:
+1
-1
@@ -98,7 +98,7 @@ useful to confirm env vars are wired correctly.
|
|||||||
|
|
||||||
## Step 4 — Custom domain (optional)
|
## Step 4 — Custom domain (optional)
|
||||||
|
|
||||||
Amplify can attach a custom domain (e.g. `check-in.fci.coop`) with
|
Amplify can attach a custom domain (e.g. `survey.fci.coop`) with
|
||||||
auto-issued TLS in a few minutes:
|
auto-issued TLS in a few minutes:
|
||||||
|
|
||||||
1. In the app, **Hosting** → **Custom domains** → **Add domain**.
|
1. In the app, **Hosting** → **Custom domains** → **Add domain**.
|
||||||
|
|||||||
+2
-2
@@ -28,7 +28,7 @@ Verify all of the above against your live CiviCRM by hitting `/api/health` (in d
|
|||||||
| `CIVI_HTTP_AUTH_USER` | only if Civi sits behind webserver-level Basic Auth | HTTP Basic Auth username. |
|
| `CIVI_HTTP_AUTH_USER` | only if Civi sits behind webserver-level Basic Auth | HTTP Basic Auth username. |
|
||||||
| `CIVI_HTTP_AUTH_PASS` | only if CIVI_HTTP_AUTH_USER is set | HTTP Basic Auth password. |
|
| `CIVI_HTTP_AUTH_PASS` | only if CIVI_HTTP_AUTH_USER is set | HTTP Basic Auth password. |
|
||||||
| `HEALTH_TOKEN` | recommended | Long random string (e.g. `openssl rand -hex 32`). Required to access `/api/health` in production. If unset, that route returns 404. |
|
| `HEALTH_TOKEN` | recommended | Long random string (e.g. `openssl rand -hex 32`). Required to access `/api/health` in production. If unset, that route returns 404. |
|
||||||
| `PUBLIC_ORIGIN` | optional | e.g. `https://check-in.fci.coop` — used in absolute self-links if needed later. |
|
| `PUBLIC_ORIGIN` | optional | e.g. `https://survey.fci.coop` — used in absolute self-links if needed later. |
|
||||||
|
|
||||||
3. **Trigger the first deploy.** Render will run `npm ci && npm run build` then `npm run start`. The platform health check hits `/healthz` (lightweight, no Civi dependency).
|
3. **Trigger the first deploy.** Render will run `npm ci && npm run build` then `npm run start`. The platform health check hits `/healthz` (lightweight, no Civi dependency).
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ Verify all of the above against your live CiviCRM by hitting `/api/health` (in d
|
|||||||
- `https://<your-render-url>/api/health?token=<HEALTH_TOKEN>` → all checks should be green
|
- `https://<your-render-url>/api/health?token=<HEALTH_TOKEN>` → all checks should be green
|
||||||
- Visit `https://<your-render-url>/?cid=<test-individual>&cs=<their-checksum>` → form loads with prefill
|
- Visit `https://<your-render-url>/?cid=<test-individual>&cs=<their-checksum>` → form loads with prefill
|
||||||
|
|
||||||
5. **Custom domain (optional)** — Render dashboard → Custom Domain → add `check-in.fci.coop`. Update DNS to the provided CNAME. Render auto-issues a Let's Encrypt cert.
|
5. **Custom domain (optional)** — Render dashboard → Custom Domain → add `survey.fci.coop`. Update DNS to the provided CNAME. Render auto-issues a Let's Encrypt cert.
|
||||||
|
|
||||||
## Security defaults
|
## Security defaults
|
||||||
|
|
||||||
|
|||||||
+15
-15
@@ -1,10 +1,10 @@
|
|||||||
# Email link delivery
|
# Email link delivery
|
||||||
|
|
||||||
The check-in form is reached via a personalized URL that carries the
|
The survey form is reached via a personalized URL that carries the
|
||||||
contact's CiviCRM ID + a server-issued checksum:
|
contact's CiviCRM ID + a server-issued checksum:
|
||||||
|
|
||||||
```
|
```
|
||||||
https://check-in.fci.coop/?cid=<contact_id>&cs=<checksum>
|
https://survey.fci.coop/?cid=<contact_id>&cs=<checksum>
|
||||||
```
|
```
|
||||||
|
|
||||||
This document covers the three pieces needed to actually get those links
|
This document covers the three pieces needed to actually get those links
|
||||||
@@ -24,10 +24,10 @@ The preview endpoint (#3) is a debugging convenience.
|
|||||||
In CiviCRM:
|
In CiviCRM:
|
||||||
|
|
||||||
1. Navigate to **Mailings → Message Templates → Add Message Template**.
|
1. Navigate to **Mailings → Message Templates → Add Message Template**.
|
||||||
2. Title: `Co-op Check-in invitation`
|
2. Title: `Co-op Survey invitation`
|
||||||
3. Subject:
|
3. Subject:
|
||||||
```
|
```
|
||||||
Time for your co-op check-in
|
Time for your co-op survey
|
||||||
```
|
```
|
||||||
4. Plain-text body (substitute your real domain):
|
4. Plain-text body (substitute your real domain):
|
||||||
|
|
||||||
@@ -38,8 +38,8 @@ In CiviCRM:
|
|||||||
month. The form pre-fills your prior responses — you only need to update
|
month. The form pre-fills your prior responses — you only need to update
|
||||||
what's changed.
|
what's changed.
|
||||||
|
|
||||||
Open your check-in:
|
Open your survey:
|
||||||
https://check-in.fci.coop/?cid={contact.contact_id}&cs={contact.checksum}
|
https://survey.fci.coop/?cid={contact.contact_id}&cs={contact.checksum}
|
||||||
|
|
||||||
The link is personalized to you and expires in 14 days. If you no longer
|
The link is personalized to you and expires in 14 days. If you no longer
|
||||||
have it, reply to this email and we'll send a fresh one.
|
have it, reply to this email and we'll send a fresh one.
|
||||||
@@ -58,11 +58,11 @@ In CiviCRM:
|
|||||||
what's changed.</p>
|
what's changed.</p>
|
||||||
|
|
||||||
<p style="margin: 24px 0;">
|
<p style="margin: 24px 0;">
|
||||||
<a href="https://check-in.fci.coop/?cid={contact.contact_id}&cs={contact.checksum}"
|
<a href="https://survey.fci.coop/?cid={contact.contact_id}&cs={contact.checksum}"
|
||||||
style="display: inline-block; background: #3a5520; color: #fafaf7;
|
style="display: inline-block; background: #3a5520; color: #fafaf7;
|
||||||
padding: 10px 20px; border-radius: 6px; text-decoration: none;
|
padding: 10px 20px; border-radius: 6px; text-decoration: none;
|
||||||
font-weight: 500;">
|
font-weight: 500;">
|
||||||
Open your check-in
|
Open your survey
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -95,14 +95,14 @@ Best for: low volume, one-at-a-time, or you want to review each send.
|
|||||||
1. Open the **organization's contact record** in CiviCRM.
|
1. Open the **organization's contact record** in CiviCRM.
|
||||||
2. **Relationships** tab → find the row with **"Primary Contact"** → click the related individual's name.
|
2. **Relationships** tab → find the row with **"Primary Contact"** → click the related individual's name.
|
||||||
3. On the individual's contact view: **Actions → Send Email**.
|
3. On the individual's contact view: **Actions → Send Email**.
|
||||||
4. **Use Template**: select `Co-op Check-in invitation`. The subject and body populate; tokens render in the preview.
|
4. **Use Template**: select `Co-op Survey invitation`. The subject and body populate; tokens render in the preview.
|
||||||
5. **Send**. CiviCRM logs the email as an Activity on the contact.
|
5. **Send**. CiviCRM logs the email as an Activity on the contact.
|
||||||
|
|
||||||
Repeat per contact. Slow but bulletproof.
|
Repeat per contact. Slow but bulletproof.
|
||||||
|
|
||||||
### Option B — Bulk: CiviMail (campaign-style send)
|
### Option B — Bulk: CiviMail (campaign-style send)
|
||||||
|
|
||||||
Best for: send the check-in invitation to every active co-op at once (e.g. monthly).
|
Best for: send the survey invitation to every active co-op at once (e.g. monthly).
|
||||||
|
|
||||||
1. Build a Smart Group of contacts whose Primary Contact relationships point at orgs in active stages. Example query:
|
1. Build a Smart Group of contacts whose Primary Contact relationships point at orgs in active stages. Example query:
|
||||||
- **Contacts** → **Advanced Search**
|
- **Contacts** → **Advanced Search**
|
||||||
@@ -112,7 +112,7 @@ Best for: send the check-in invitation to every active co-op at once (e.g. month
|
|||||||
|
|
||||||
2. **Mailings → New Mailing**.
|
2. **Mailings → New Mailing**.
|
||||||
3. Recipients: the smart group above.
|
3. Recipients: the smart group above.
|
||||||
4. Choose template: `Co-op Check-in invitation`.
|
4. Choose template: `Co-op Survey invitation`.
|
||||||
5. Schedule send.
|
5. Schedule send.
|
||||||
|
|
||||||
Each recipient gets their own checksum embedded in the URL — CiviMail
|
Each recipient gets their own checksum embedded in the URL — CiviMail
|
||||||
@@ -125,10 +125,10 @@ Best for: a button-on-the-org-record workflow.
|
|||||||
Setup:
|
Setup:
|
||||||
|
|
||||||
1. **Administer → CiviRules → Manage Rules → New Rule**.
|
1. **Administer → CiviRules → Manage Rules → New Rule**.
|
||||||
2. Title: `Send Co-op Check-in invitation`.
|
2. Title: `Send Co-op Survey invitation`.
|
||||||
3. **Trigger**: pick a "manually trigger from org row" action if your CiviRules version supports it. Otherwise: trigger on org Stage change (auto-fires when staff advance an org).
|
3. **Trigger**: pick a "manually trigger from org row" action if your CiviRules version supports it. Otherwise: trigger on org Stage change (auto-fires when staff advance an org).
|
||||||
4. **Action**: `Send email to contact via message template`.
|
4. **Action**: `Send email to contact via message template`.
|
||||||
- Template: `Co-op Check-in invitation`.
|
- Template: `Co-op Survey invitation`.
|
||||||
- Recipient: **Contact in relationship** → "Primary Contact" → side B (the Individual).
|
- Recipient: **Contact in relationship** → "Primary Contact" → side B (the Individual).
|
||||||
5. Save.
|
5. Save.
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ contact/org context for verification.
|
|||||||
**Request:**
|
**Request:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl "https://check-in.fci.coop/api/preview-link?cid=513&token=$HEALTH_TOKEN"
|
curl "https://survey.fci.coop/api/preview-link?cid=513&token=$HEALTH_TOKEN"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Response:**
|
**Response:**
|
||||||
@@ -165,7 +165,7 @@ curl "https://check-in.fci.coop/api/preview-link?cid=513&token=$HEALTH_TOKEN"
|
|||||||
"orgId": 9609,
|
"orgId": 9609,
|
||||||
"orgName": "A Sample Food Co-op",
|
"orgName": "A Sample Food Co-op",
|
||||||
"orgStage": "Organizing",
|
"orgStage": "Organizing",
|
||||||
"url": "https://check-in.fci.coop/?cid=513&cs=8d1f...",
|
"url": "https://survey.fci.coop/?cid=513&cs=8d1f...",
|
||||||
"checksum": "8d1f...",
|
"checksum": "8d1f...",
|
||||||
"ttlHours": 336
|
"ttlHours": 336
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Co-op Check-in
|
# Co-op Survey
|
||||||
|
|
||||||
A tokenized, mobile-friendly web form that lets external co-op contacts
|
A tokenized, mobile-friendly web form that lets external co-op contacts
|
||||||
update their organization's tracking data on CiviCRM, plus a read-only
|
update their organization's tracking data on CiviCRM, plus a read-only
|
||||||
@@ -11,8 +11,8 @@ Each co-op has a designated **Primary Contact** (the individual) linked
|
|||||||
to the **Organization** record in CiviCRM. Staff send that contact a
|
to the **Organization** record in CiviCRM. Staff send that contact a
|
||||||
personalized link generated against the contact's CiviCRM checksum:
|
personalized link generated against the contact's CiviCRM checksum:
|
||||||
|
|
||||||
- `https://check-in.fci.coop/?cid=<contactId>&cs=<checksum>` — the form
|
- `https://survey.fci.coop/?cid=<contactId>&cs=<checksum>` — the form
|
||||||
- `https://check-in.fci.coop/report?cid=<contactId>&cs=<checksum>` — the report
|
- `https://survey.fci.coop/report?cid=<contactId>&cs=<checksum>` — the report
|
||||||
|
|
||||||
When the link is opened, the app verifies the checksum against CiviCRM,
|
When the link is opened, the app verifies the checksum against CiviCRM,
|
||||||
resolves the organization through the Primary Contact relationship, and
|
resolves the organization through the Primary Contact relationship, and
|
||||||
@@ -24,12 +24,12 @@ Build → Fulfill & Stabilize). The org's current stage controls which
|
|||||||
sections are editable; past and current stages are open for editing,
|
sections are editable; past and current stages are open for editing,
|
||||||
future stages render as previews with their fields locked so the co-op
|
future stages render as previews with their fields locked so the co-op
|
||||||
can see the framework ahead. Fields prefill with each value's most
|
can see the framework ahead. Fields prefill with each value's most
|
||||||
recent non-empty entry from past check-ins. On submit, a new
|
recent non-empty entry from past surveys. On submit, a new
|
||||||
"Check-in (organizing)" activity is created; nothing is overwritten.
|
"Check-in (organizing)" activity is created; nothing is overwritten.
|
||||||
|
|
||||||
**Stage authority.** The current stage is derived from the most recent
|
**Stage authority.** The current stage is derived from the most recent
|
||||||
"Check-in (organizing)" activity whose Stage field is set. Staff own
|
"Check-in (organizing)" activity whose Stage field is set. Staff own
|
||||||
stage transitions by manually setting Stage on a check-in activity they
|
stage transitions by manually setting Stage on a "Check-in (organizing)" activity they
|
||||||
create; the form itself never writes Stage, so org self-submissions
|
create; the form itself never writes Stage, so org self-submissions
|
||||||
can't override a staff transition. Orgs with no stage-bearing activity
|
can't override a staff transition. Orgs with no stage-bearing activity
|
||||||
default to "Inquiry."
|
default to "Inquiry."
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* GET /api/preview-link?cid=<contactId>&token=<HEALTH_TOKEN>
|
* GET /api/preview-link?cid=<contactId>&token=<HEALTH_TOKEN>
|
||||||
*
|
*
|
||||||
* Returns a ready-to-send check-in URL for a given contact, plus enough
|
* Returns a ready-to-send survey URL for a given contact, plus enough
|
||||||
* context for staff to verify it's the right org. Used for:
|
* context for staff to verify it's the right org. Used for:
|
||||||
* - Generating links to paste into ad-hoc emails (or external tools)
|
* - Generating links to paste into ad-hoc emails (or external tools)
|
||||||
* - Testing a contact's setup before sending the real CiviCRM email
|
* - Testing a contact's setup before sending the real CiviCRM email
|
||||||
|
|||||||
@@ -49,11 +49,11 @@ const STUB_PAYLOAD: ReportPayload = (() => {
|
|||||||
orgName: "Sample Co-op (stub)",
|
orgName: "Sample Co-op (stub)",
|
||||||
currentStage: "Organizing",
|
currentStage: "Organizing",
|
||||||
activities: [
|
activities: [
|
||||||
{ id: 9012, date: daysAgo(3), subject: "Co-op Check-in (form submission)" },
|
{ id: 9012, date: daysAgo(3), subject: "Co-op Survey (form submission)" },
|
||||||
{ id: 9008, date: daysAgo(34), subject: "Co-op Check-in (form submission)" },
|
{ id: 9008, date: daysAgo(34), subject: "Co-op Survey (form submission)" },
|
||||||
{ id: 9001, date: daysAgo(62), stage: "Organizing", subject: "Stage transition (staff)" },
|
{ id: 9001, date: daysAgo(62), stage: "Organizing", subject: "Stage transition (staff)" },
|
||||||
{ id: 8995, date: daysAgo(95), subject: "Co-op Check-in (form submission)" },
|
{ id: 8995, date: daysAgo(95), subject: "Co-op Survey (form submission)" },
|
||||||
{ id: 8980, date: daysAgo(180), stage: "Inquiry", subject: "Initial check-in (staff)" },
|
{ id: 8980, date: daysAgo(180), stage: "Inquiry", subject: "Initial survey (staff)" },
|
||||||
],
|
],
|
||||||
fieldHistory: {
|
fieldHistory: {
|
||||||
Peer_Group_Participation: [
|
Peer_Group_Participation: [
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export async function POST(req: Request) {
|
|||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
error: appEnv().isProduction
|
error: appEnv().isProduction
|
||||||
? "Could not save your check-in. Please try again, or contact your engagement coordinator."
|
? "Could not save your survey. Please try again, or contact your engagement coordinator."
|
||||||
: `Save failed: ${redact(msg)}`,
|
: `Save failed: ${redact(msg)}`,
|
||||||
},
|
},
|
||||||
{ status: 500 },
|
{ status: 500 },
|
||||||
@@ -110,7 +110,7 @@ async function runSubmit(cid: string, cs: string, values: Record<string, unknown
|
|||||||
"status_id:name": "Completed",
|
"status_id:name": "Completed",
|
||||||
target_contact_id: orgId,
|
target_contact_id: orgId,
|
||||||
source_contact_id: Number(cid),
|
source_contact_id: Number(cid),
|
||||||
subject: "Co-op Check-in (form submission)",
|
subject: "Co-op Survey (form submission)",
|
||||||
};
|
};
|
||||||
for (const [name, value] of Object.entries(values)) {
|
for (const [name, value] of Object.entries(values)) {
|
||||||
const field = FIELD_BY_NAME.get(name);
|
const field = FIELD_BY_NAME.get(name);
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ const body = Open_Sans({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Co-op Check-in · Food Co-op Initiative",
|
title: "Co-op Survey · Food Co-op Initiative",
|
||||||
description:
|
description:
|
||||||
"Update your co-op's progress through the FCI organizing Framework. A survey for food co-ops in development.",
|
"Update your co-op's progress through the FCI organizing Framework. A survey for food co-ops in development.",
|
||||||
robots: { index: false, follow: false }, // Form pages are tokenized; not for crawlers.
|
robots: { index: false, follow: false }, // Form pages are tokenized; not for crawlers.
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ function ReportIntro() {
|
|||||||
</h1>
|
</h1>
|
||||||
<p className="mt-4 max-w-prose text-[17px] leading-relaxed text-ink-soft">
|
<p className="mt-4 max-w-prose text-[17px] leading-relaxed text-ink-soft">
|
||||||
A read-only summary of every value your co-op has shared through past
|
A read-only summary of every value your co-op has shared through past
|
||||||
check-ins, grouped by stage. The most recent entry sits at the top of
|
surveys, grouped by stage. The most recent entry sits at the top of
|
||||||
each row; expand a row to see how a number or note has changed over
|
each row; expand a row to see how a number or note has changed over
|
||||||
time.
|
time.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ function SubmissionContextHeader({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<header className="rounded-lg border border-rule bg-paper-2/40 px-6 py-5 sm:px-7 sm:py-6">
|
<header className="rounded-lg border border-rule bg-paper-2/40 px-6 py-5 sm:px-7 sm:py-6">
|
||||||
<p className="text-[11px] uppercase tracking-[0.18em] text-ink-mute">Check-in for</p>
|
<p className="text-[11px] uppercase tracking-[0.18em] text-ink-mute">Survey for</p>
|
||||||
<h1 className="mt-1 font-display text-3xl font-medium leading-tight tracking-tight text-ink sm:text-[34px]">
|
<h1 className="mt-1 font-display text-3xl font-medium leading-tight tracking-tight text-ink sm:text-[34px]">
|
||||||
{orgName}
|
{orgName}
|
||||||
</h1>
|
</h1>
|
||||||
@@ -551,7 +551,7 @@ function SubmitBar({
|
|||||||
} else if (state.kind === "submitting") {
|
} else if (state.kind === "submitting") {
|
||||||
secondary = (
|
secondary = (
|
||||||
<p className="truncate text-xs text-ink-soft" role="status">
|
<p className="truncate text-xs text-ink-soft" role="status">
|
||||||
Saving your check-in…
|
Saving your survey…
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
} else if (viewedSectionLabel && viewedRank != null) {
|
} else if (viewedSectionLabel && viewedRank != null) {
|
||||||
@@ -604,10 +604,10 @@ function SubmitBar({
|
|||||||
>
|
>
|
||||||
{state.kind === "submitting" ? (
|
{state.kind === "submitting" ? (
|
||||||
<>
|
<>
|
||||||
<Spinner /> Saving check-in…
|
<Spinner /> Saving survey…
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>Submit check-in</>
|
<>Submit survey</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -636,7 +636,7 @@ function LoadingState() {
|
|||||||
aria-hidden
|
aria-hidden
|
||||||
className="mx-auto mb-4 h-7 w-7 animate-spin rounded-full border-[1.5px] border-rule border-t-leaf-700"
|
className="mx-auto mb-4 h-7 w-7 animate-spin rounded-full border-[1.5px] border-rule border-t-leaf-700"
|
||||||
/>
|
/>
|
||||||
<p className="font-display text-base text-ink-soft italic">Loading your check-in…</p>
|
<p className="font-display text-base text-ink-soft italic">Loading your survey…</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -663,10 +663,10 @@ function SuccessDestination({
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h2 className="mt-5 font-display text-2xl font-medium leading-tight tracking-tight text-ink sm:text-3xl">
|
<h2 className="mt-5 font-display text-2xl font-medium leading-tight tracking-tight text-ink sm:text-3xl">
|
||||||
Check-in saved
|
Survey saved
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mx-auto mt-3 max-w-prose text-[15px] leading-relaxed text-ink-soft">
|
<p className="mx-auto mt-3 max-w-prose text-[15px] leading-relaxed text-ink-soft">
|
||||||
Thank you. We've recorded this check-in for{" "}
|
Thank you. We've recorded this survey for{" "}
|
||||||
<span className="font-medium text-ink">{orgName}</span>. Your engagement coordinator will see
|
<span className="font-medium text-ink">{orgName}</span>. Your engagement coordinator will see
|
||||||
it on their next review.
|
it on their next review.
|
||||||
</p>
|
</p>
|
||||||
@@ -676,7 +676,7 @@ function SuccessDestination({
|
|||||||
onClick={onAnother}
|
onClick={onAnother}
|
||||||
className="inline-flex items-center justify-center rounded-md border border-rule bg-paper px-5 py-2 text-sm font-medium text-ink-soft transition hover:bg-paper-2/60 focus:outline-none focus-visible:ring-2 focus-visible:ring-leaf-500/40"
|
className="inline-flex items-center justify-center rounded-md border border-rule bg-paper px-5 py-2 text-sm font-medium text-ink-soft transition hover:bg-paper-2/60 focus:outline-none focus-visible:ring-2 focus-visible:ring-leaf-500/40"
|
||||||
>
|
>
|
||||||
Submit another check-in
|
Submit another survey
|
||||||
</button>
|
</button>
|
||||||
<p className="text-xs text-ink-mute">It's safe to close this window.</p>
|
<p className="text-xs text-ink-mute">It's safe to close this window.</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -691,7 +691,7 @@ function ErrorState({ message }: { message: string }) {
|
|||||||
className="rounded-lg border-2 border-clay-200 bg-clay-100/30 px-6 py-7"
|
className="rounded-lg border-2 border-clay-200 bg-clay-100/30 px-6 py-7"
|
||||||
>
|
>
|
||||||
<h2 className="font-display text-xl font-medium text-clay-700">
|
<h2 className="font-display text-xl font-medium text-clay-700">
|
||||||
We couldn't open your check-in.
|
We couldn't open your survey.
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-3 text-sm leading-relaxed text-ink-soft">{message}</p>
|
<p className="mt-3 text-sm leading-relaxed text-ink-soft">{message}</p>
|
||||||
<p className="mt-4 text-sm text-ink-soft">
|
<p className="mt-4 text-sm text-ink-soft">
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ function ReportContextHeader({
|
|||||||
{currentStageLabel || "—"}
|
{currentStageLabel || "—"}
|
||||||
</p>
|
</p>
|
||||||
<dl className="mt-5 grid grid-cols-3 gap-3 border-t border-rule-soft pt-4 text-sm sm:gap-6">
|
<dl className="mt-5 grid grid-cols-3 gap-3 border-t border-rule-soft pt-4 text-sm sm:gap-6">
|
||||||
<Stat label="Check-ins" value={String(totalActivities)} />
|
<Stat label="Surveys" value={String(totalActivities)} />
|
||||||
<Stat label="Fields tracked" value={String(totalFieldsTracked)} />
|
<Stat label="Fields tracked" value={String(totalFieldsTracked)} />
|
||||||
<Stat
|
<Stat
|
||||||
label="Span"
|
label="Span"
|
||||||
@@ -1414,7 +1414,7 @@ function EmptyState() {
|
|||||||
<div className="rounded-lg border border-dashed border-rule bg-paper-2/30 px-6 py-10 text-center">
|
<div className="rounded-lg border border-dashed border-rule bg-paper-2/30 px-6 py-10 text-center">
|
||||||
<p className="font-display text-lg text-ink-soft">No entries on file yet.</p>
|
<p className="font-display text-lg text-ink-soft">No entries on file yet.</p>
|
||||||
<p className="mt-2 text-sm text-ink-mute">
|
<p className="mt-2 text-sm text-ink-mute">
|
||||||
Your co-op's first check-in will appear here once it's submitted.
|
Your co-op's first survey will appear here once it's submitted.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function SiteHeader() {
|
|||||||
className="h-12 w-auto sm:h-14"
|
className="h-12 w-auto sm:h-14"
|
||||||
/>
|
/>
|
||||||
<span className="hidden text-[11px] uppercase tracking-[0.18em] text-ink-mute sm:inline-block sm:border-l sm:border-rule sm:pl-4">
|
<span className="hidden text-[11px] uppercase tracking-[0.18em] text-ink-mute sm:inline-block sm:border-l sm:border-rule sm:pl-4">
|
||||||
Co-op Check-in
|
Co-op Survey
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
<nav aria-label="Primary">
|
<nav aria-label="Primary">
|
||||||
|
|||||||
+8
-8
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Form definition for the Org Engagement Check-in form.
|
* Form definition for the Org Engagement Survey form.
|
||||||
*
|
*
|
||||||
* Field references and types are sourced from the live CiviCRM DEV
|
* Field references and types are sourced from the live CiviCRM DEV
|
||||||
* (`client.crm.fci.coop`) inventory pulled 2026-05-09 via APIv4
|
* (`client.crm.fci.coop`) inventory pulled 2026-05-09 via APIv4
|
||||||
@@ -49,13 +49,13 @@ const G3 = "Stage_3";
|
|||||||
const G4 = "Stage_4";
|
const G4 = "Stage_4";
|
||||||
const G5 = "Stage_5";
|
const G5 = "Stage_5";
|
||||||
|
|
||||||
// Stage 0 — Check-in (always visible)
|
// Stage 0 — Survey (always visible)
|
||||||
const stage0: StageSectionConfig = {
|
const stage0: StageSectionConfig = {
|
||||||
rank: 0,
|
rank: 0,
|
||||||
id: "stage_0",
|
id: "stage_0",
|
||||||
label: "Check-in (organizing)",
|
label: "Check-in (organizing)",
|
||||||
intro:
|
// intro:
|
||||||
"Core check-in fields. These are visible at every stage and capture the data we follow over time across the lifecycle of the co-op.",
|
// "Core survey fields. These are visible at every stage and capture the data we follow over time across the lifecycle of the co-op.",
|
||||||
fields: [
|
fields: [
|
||||||
// current_stage is a UI-only readonly field. Its value is the Civi
|
// current_stage is a UI-only readonly field. Its value is the Civi
|
||||||
// option *value* (e.g. "Organizing") sourced by /api/data from the
|
// option *value* (e.g. "Organizing") sourced by /api/data from the
|
||||||
@@ -218,7 +218,7 @@ const stage0: StageSectionConfig = {
|
|||||||
type: "currency",
|
type: "currency",
|
||||||
visibleWhen: visibleAtOrAfter(S.Stabilize),
|
visibleWhen: visibleAtOrAfter(S.Stabilize),
|
||||||
civiField: `${G0}.Member_equity_raised`,
|
civiField: `${G0}.Member_equity_raised`,
|
||||||
help: "Member-owner equity raised, as of the time of check-in",
|
help: "Member-owner equity raised, as of the time of survey",
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// name: "Member_loans_total",
|
// name: "Member_loans_total",
|
||||||
@@ -232,7 +232,7 @@ const stage0: StageSectionConfig = {
|
|||||||
type: "currency",
|
type: "currency",
|
||||||
visibleWhen: visibleAtOrAfter(S.Stabilize),
|
visibleWhen: visibleAtOrAfter(S.Stabilize),
|
||||||
civiField: `${G0}.Member_loans_raised`,
|
civiField: `${G0}.Member_loans_raised`,
|
||||||
help: "Total amount (USD) raised from member-owner loans, as of the time of check-in",
|
help: "Total amount (USD) raised from member-owner loans, as of the time of survey",
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// name: "Member_preferred_shares_total",
|
// name: "Member_preferred_shares_total",
|
||||||
@@ -498,7 +498,7 @@ const stage3: StageSectionConfig = {
|
|||||||
fieldGroups: [
|
fieldGroups: [
|
||||||
{ id: "site", fields: ["Site_Letter_of_Intent_Date", "Site_Letter_of_Intent_Upload"] },
|
{ id: "site", fields: ["Site_Letter_of_Intent_Date", "Site_Letter_of_Intent_Upload"] },
|
||||||
{ id: "store_design", fields: ["Store_Designer", "Store_Design_Plan_Completion"] },
|
{ id: "store_design", fields: ["Store_Designer", "Store_Design_Plan_Completion"] },
|
||||||
{ id: "cap_camp", fields: ["Capital_Campaign_Owner_Participation_", "Capital_Campaign_Average_Owner_Investment"]},
|
// { id: "cap_camp", fields: ["Capital_Campaign_Owner_Participation_", "Capital_Campaign_Average_Owner_Investment"]},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -713,7 +713,7 @@ const stage5: StageSectionConfig = {
|
|||||||
|
|
||||||
export const formConfig: FormConfig = {
|
export const formConfig: FormConfig = {
|
||||||
id: "org_engagement_check_in",
|
id: "org_engagement_check_in",
|
||||||
title: "Co-op Check-in",
|
title: "Co-op Survey",
|
||||||
subtitle:
|
subtitle:
|
||||||
"Update tracking data for your co-op as you progress through the organizing stages. The questions you'll see depend on where you are in the framework.",
|
"Update tracking data for your co-op as you progress through the organizing stages. The questions you'll see depend on where you are in the framework.",
|
||||||
stageField: "current_stage",
|
stageField: "current_stage",
|
||||||
|
|||||||
+1
-1
@@ -203,7 +203,7 @@ export interface FormConfig {
|
|||||||
/**
|
/**
|
||||||
* Identifying details for the contact submitting the form, derived from the
|
* Identifying details for the contact submitting the form, derived from the
|
||||||
* cid resolved by /api/data. Surfaced as readonly fields in Stage 0 so the
|
* cid resolved by /api/data. Surfaced as readonly fields in Stage 0 so the
|
||||||
* person filling out the check-in can confirm who's logged as the submitter.
|
* person filling out the survey can confirm who's logged as the submitter.
|
||||||
*/
|
*/
|
||||||
export interface ContactIdentity {
|
export interface ContactIdentity {
|
||||||
firstName: string;
|
firstName: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user