Opt-In / Opt-Out program flow#34
Conversation
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
| <Loading /> | ||
| {/if} | ||
|
|
||
| <Modal |
There was a problem hiding this comment.
Let's use a PanelFormDialog here, it will behave a lot better long term since we don't know what downstream might want to do with their prompt. Also much easier to wire up than this was.
|
|
||
| <Modal | ||
| bind:open | ||
| modalHeading={`${optIn ? 'Opt in to' : 'Opt out of'} ${prompt?.title}?`} |
There was a problem hiding this comment.
Shouldn't prompt?.title be the program/application title?
| on:close={() => { prompt = {} }} | ||
| class='opt-out-modal' | ||
| > | ||
| {#key prompt.id} |
There was a problem hiding this comment.
This {#key} thing was specific to how the prompt screen was working. You won't need it here.
| moot: 0 | 1 | ||
| locked: 0 | 1 | ||
| invalidated: 0 | 1 | ||
| optOut: 0 | 1 |
There was a problem hiding this comment.
Lots of API-side code hanging around that shouldn't be necessary. More details in other comments.
| <div class="gap-4 flex flex-col"> | ||
| {#if initialData.optOut} | ||
| <p>By opting back in, you will be eligible for this program.</p> | ||
| <Checkbox labelText='I understand and would like to opt in' on:click={updateOpposite} /> |
There was a problem hiding this comment.
This was a tough design to try to match. I would recommend pushing back and asking for a radio button, but if necessary something like this:
export let data: { optOut?: boolean, optOutUnderstand?: boolean, optInUnderstand?: boolean }
const wasOptedOut = data.optOut
const wasOptedIn = !wasOptedOut
...
<FieldCheckbox path="optInUnderstand" labelText="I understand opt in" conditional={wasOptedOut} />
<FieldCheckbox path="optOutUnderstand" labelText="I understand opt out" conditional={wasOptedIn} />
<FieldHidden path="optOut" value={(wasOptedOut && !data.optInUnderstand) || (wasOptedIn && data.optOutUnderstand)} />The conditional will hide the checkboxes and keep their values undefined. There will be extra data in the prompt but that's no big deal and optOut will change as you like. No need to manipulate the store.
| > | ||
| {#key prompt.id} | ||
| <Form bind:store hideFallbackMessage unsavedWarning submit={onSubmit} validate={onValidate} preloadAsDraft={!prompt.hasSavedData} preload={prompt.preloadData} let:data> | ||
| <svelte:component this={def!.formComponent} {data} appRequestId={appRequest.id} appRequestData={appRequest.data} fetched={prompt.fetchedData} configData={prompt.configurationData} gatheredConfigData={prompt.gatheredConfigData} store={store} /> |
There was a problem hiding this comment.
I see why you did it but I wouldn't add the store here without adding it to the other places that render prompt components. We have to present a consistent set of props to the downstream.
I probably wouldn't add it, as it's already in context. You can do this inside a prompt:
import { FORM_CONTEXT, type FormStore } from '@txstate-mws/svelte-forms'
const store = getContext<FormStore>(FORM_CONTEXT)| description: 'Opt Out', | ||
| schema: OptOutSchema, | ||
| optOut: true, | ||
| prestage: () => ({ |
There was a problem hiding this comment.
oof, I see why you did this and it's going to be confusing for folks on the regular, but I think the requirement just needs to treat undefined as MET instead of trying to use prestage to inject data into here.
| resolve: (data, config) => { | ||
| const promptData = data['opt_out_prompt'] as OptOutData | ||
| if (promptData?.optOut) return { status: RequirementStatus.DISQUALIFYING } | ||
| if (promptData?.optOut == null) return { status: RequirementStatus.PENDING } |
There was a problem hiding this comment.
This is what I was referring to in the earlier comment. Don't return PENDING here, just return MET or NOT_APPLICABLE if they have never opened the modal.
| prestage: () => ({ | ||
| optOut: false | ||
| }), | ||
| validate: (data, config) => { |
There was a problem hiding this comment.
I feel like this validate could be omitted once the requirement is updated to accept undefined as MET. No big deal to include it but I want to be sure it's not needed because that'd be an ugly thing for downstream to have to remember to do.
|
So, after we spoke yesterday about the problems you were having with the opt-out prompt being marked as UNREACHABLE, I realize that the API probably does have to know about opt-out. The basic goal that I was pursuing while designing the architecture was to ask only as many questions as we must, to get the applicant approved or denied. So the visibility/unreachable logic makes this assumption: if the An opt-out breaks this assumption, because the requirement's resolve function is MET by default, but you can answer the opt-out prompt to switch it to DISQUALIFYING. So the prompt should remain reachable even though answering it is not required to come to a decision. I wanted to get that all down for you to improve understanding, but to break it down into something actionable, I think the answer is to move the On the API side, one additional change is needed to look at |
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
txstate-etc/reqquest-txstate#267