Skip to content

Commit

Permalink
Merge pull request #541 from wmde/C24_WMDE_Mobile_DE_10
Browse files Browse the repository at this point in the history
Implement "Yes-No-Address-Form"
  • Loading branch information
gbirke authored Nov 27, 2024
2 parents f3a0afc + 762330b commit a28123e
Show file tree
Hide file tree
Showing 8 changed files with 860 additions and 6 deletions.
10 changes: 9 additions & 1 deletion src/components/pages/DonationForm.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<template>
<FeatureToggle default-template="campaigns.address_pages.legacy">
<template #campaigns.address_pages.legacy>
<StandardDonationForm v-bind="props"/>
<FeatureToggle default-template="campaigns.address_type_choice.default">
<template #campaigns.address_type_choice.default>
<StandardDonationForm v-bind="props"/>
</template>
<template #campaigns.address_type_choice.choice>
<ChoiceDonationForm v-bind="props" />
</template>
</FeatureToggle>
</template>
<template #campaigns.address_pages.test_02>
<ReceiptDonationForm v-bind="props"/>
Expand All @@ -17,6 +24,7 @@ import { Salutation } from '@src/view_models/Salutation';
import { CampaignValues } from '@src/view_models/CampaignValues';
import StandardDonationForm from '@src/components/pages/donation_form/SubPages/DonationForm.vue';
import ReceiptDonationForm from '@src/components/pages/donation_form/SubPages/DonationFormReceipt.vue';
import ChoiceDonationForm from '@src/components/pages/donation_form/SubPages/DonationFormAnonymousChoice.vue';
defineOptions( {
name: 'DonationForm',
Expand Down
45 changes: 45 additions & 0 deletions src/components/pages/donation_form/AddressOptOut/ErrorSummary.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<ErrorSummary
:is-visible="showErrorSummary"
:items="[
{
validity: store.state.payment.validity.amount,
message: $t( 'error_summary_amount' ),
focusElement: 'amount-500',
scrollElement: 'payment-form-amount-scroll-target',
},
{
validity: store.state.payment.validity.type,
message: $t( 'error_summary_payment_type' ),
focusElement: 'paymentType-0',
scrollElement: 'payment-form-type-scroll-target',
},
{
validity: store.state.bankdata.validity.iban,
message: $t( 'donation_form_payment_iban_error' ),
focusElement: 'iban',
scrollElement: 'iban-scroll-target'
},
{
validity: store.state.address.validity.addressType,
message: $t( 'error_summary_address_type_opt_out' ),
focusElement: 'addressOptOut-1',
scrollElement: 'address-opt-out-scroll-target',
},
]"
/>
</template>

<script setup lang="ts">
import ErrorSummary from '@src/components/shared/validation_summary/ErrorSummary.vue';
import { useStore } from 'vuex';
const store = useStore();
interface Props {
showErrorSummary: boolean
}
defineProps<Props>();
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Store } from 'vuex';
import { Ref, ref, watch } from 'vue';
import { action } from '@src/store/util';
import { AddressTypeModel } from '@src/view_models/AddressTypeModel';

export interface AddressOptOutModel {
addressOptIn: Ref<boolean|null>;
previousAddressType: Ref<AddressTypeModel>
}

function getInitialAddressOptInValue( store: Store<any> ): boolean|null {
if ( store.state.address.addressType === AddressTypeModel.UNSET ) {
return null;
}
return store.state.address.addressType !== AddressTypeModel.ANON;
}

export function useAddressOptOutModel( store: Store<any> ): AddressOptOutModel {
const addressOptIn = ref<boolean|null>( getInitialAddressOptInValue( store ) );
const previousAddressType = ref<AddressTypeModel>( AddressTypeModel.PERSON );

watch( addressOptIn, ( newValue: boolean | null ) => {
if ( newValue === true ) {
store.dispatch( action( 'address', 'setAddressType' ), previousAddressType.value );
} else {
const currentAddressType = store.state.address.addressType;
if ( currentAddressType !== AddressTypeModel.ANON && currentAddressType !== AddressTypeModel.UNSET ) {
previousAddressType.value = currentAddressType;
}
store.dispatch( action( 'address', 'setAddressType' ), AddressTypeModel.ANON );
}
} );

return {
addressOptIn,
previousAddressType,
};
}
60 changes: 60 additions & 0 deletions src/components/pages/donation_form/AddressTypeNoAnon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>

<RadioField
name="addressType"
:options="[
{
value: AddressTypeModel.PERSON,
label: $t( 'donation_form_addresstype_option_private_addresstype_basic' ),
id: 'addressType-0'
},
{
value: AddressTypeModel.COMPANY,
label: $t( 'donation_form_addresstype_option_company_addresstype_basic' ),
id: 'addressType-1'
},
]"
:label="$t( 'donation_form_address_choice_title_addresstype_basic' )"
:disabled="disabledAddressTypes"
:show-error="addressTypeIsInvalid"
:error-message="$t( 'donation_form_section_address_error' )"
v-model="addressType"
alignment="column"
>
</RadioField>

</template>

<script setup lang="ts">
import RadioField from '@src/components/shared/form_fields/RadioField.vue';
import { AddressTypeModel } from '@src/view_models/AddressTypeModel';
import { ref, watch } from 'vue';
interface Props {
disabledAddressTypes: AddressTypeModel[]
isDirectDebit: boolean;
addressTypeIsInvalid: boolean;
initialAddressType?: AddressTypeModel;
}
const props = defineProps<Props>();
const emit = defineEmits( [ 'address-type' ] );
const addressType = ref<AddressTypeModel>( props.initialAddressType ?? AddressTypeModel.UNSET );
watch( addressType, newAddressType => {
emit( 'address-type', newAddressType );
} );
// When disabled address type is selected, revert to person type
watch( () => props.disabledAddressTypes, disabledAddressTypes => {
// TODO This assumes that person will never be disabled.
// If this assumption is wrong, we need to have a fallback.
if ( disabledAddressTypes !== undefined &&
disabledAddressTypes.includes( addressType.value ) ) {
addressType.value = AddressTypeModel.PERSON;
}
} );
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<template>
<div
id="donation-page-form-section-personal-data"
class="donation-page-form-section"
aria-live="assertive"
aria-labelledby="donation-form-subheading donation-form-tagline"
>
<h2 id="donation-form-subheading" class="form-subtitle">{{ $t( 'donation_form_address_subheading' ) }}</h2>
<p id="donation-form-tagline">{{ $t( 'donation_form_section_address_tagline' ) }}</p>

<form id="address-type-option" @submit="evt => evt.preventDefault()">
<ScrollTarget target-id="address-opt-out-scroll-target"/>
<RadioField
v-model="addressOptOut.addressOptIn"
name="address-opt-out"
:options="[
{ value: true, label: $t( 'yes' ), id: 'addressOptOut-0' },
{ value: false, label: $t( 'no' ), id: 'addressOptOut-1' },
]"
:label="$t( 'donation_form_section_address_opt_out' )"
:disabled="isDirectDebitPayment ? [ false ] : []"
alignment="row"
aria-describedby="donation-address-opt-out-help-text"
>
<template #intro-message>
</template>
<template #tooltip-false>
<RadioFieldHelpText v-if="isDirectDebitPayment">
{{ $t( 'donation_form_address_choice_direct_debit_disclaimer' ) }}
</RadioFieldHelpText>
</template>
</RadioField>
</form>

<form id="address-type-selection" @submit="evt => evt.preventDefault()" v-if="addressOptOut.addressOptIn === true" >
<ScrollTarget target-id="address-type-scroll-target"/>
<AddressTypeNoAnon
@address-type="$emit( 'set-address-type', $event )"
:disabledAddressTypes="[]"
:is-direct-debit="isDirectDebitPayment"
:initial-address-type="addressType"
:address-type-is-invalid="addressTypeIsInvalid"
/>
</form>

<AddressForms
v-if="addressOptOut.addressOptIn === true"
:countries="countries"
:salutations="salutations"
:address-validation-patterns="addressValidationPatterns"
:address-type="addressType"
:tracking-data="trackingData"
:campaign-values="campaignValues">
</AddressForms>
</div>
</template>

<script setup lang="ts">
import { toRef } from 'vue';
import ScrollTarget from '@src/components/shared/ScrollTarget.vue';
import AddressTypeNoAnon from '@src/components/pages/donation_form/AddressTypeNoAnon.vue';
import AddressForms from '@src/components/pages/donation_form/AddressForms.vue';
import RadioField from '@src/components/shared/form_fields/RadioField.vue';
import { CampaignValues } from '@src/view_models/CampaignValues';
import { Country } from '@src/view_models/Country';
import { Salutation } from '@src/view_models/Salutation';
import { TrackingData } from '@src/view_models/TrackingData';
import { AddressValidation } from '@src/view_models/Validation';
import { AddressTypeModel } from '@src/view_models/AddressTypeModel';
import { AddressOptOutModel } from '@src/components/pages/donation_form/AddressOptOut/useAddressOptOut';
import RadioFieldHelpText from '@src/components/shared/form_elements/RadioFieldTooltip.vue';
interface Props {
countries: Country[];
salutations: Salutation[];
trackingData: TrackingData;
campaignValues: CampaignValues;
addressValidationPatterns: AddressValidation;
isDirectDebitPayment: boolean;
disabledAddressTypes: AddressTypeModel[];
addressType: AddressTypeModel;
addressTypeIsInvalid: boolean;
addressOptOut: AddressOptOutModel
}
const props = defineProps<Props>();
defineEmits( [ 'set-address-type' ] );
const addressOptOut = toRef( props.addressOptOut );
</script>

<style lang="scss">
@use '@src/scss/settings/units';
@use 'sass:map';
.address-type-anonymous-disclaimer {
margin-top: map.get( units.$spacing, 'medium' );
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@
alignment="row"
aria-describedby="donation-receipt-help-text"
>
<template #intro-message>
<div class="form-field-intro" id="donation-receipt-help-text">
{{ $t( 'C24_WMDE_Desktop_DE_01_help_text' ) }}
</div>
</template>
</RadioField>

<AddressFields
Expand Down
Loading

0 comments on commit a28123e

Please sign in to comment.