Skip to content

Commit

Permalink
Implement VAR for C24_WMDE_Desktop_DE_23
Browse files Browse the repository at this point in the history
VAR has a donation receipt checkbox that pre-fills
the option on the main donation form.

Ticket: https://phabricator.wikimedia.org/T382307
  • Loading branch information
Abban committed Dec 19, 2024
1 parent bc6fb3e commit 3798196
Show file tree
Hide file tree
Showing 15 changed files with 650 additions and 10 deletions.
2 changes: 1 addition & 1 deletion banners/desktop/C24_WMDE_Desktop_DE_23/banner_var.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createVueApp } from '@src/createVueApp';

import './styles/styles.scss';
import './styles/styles_var.scss';

import BannerConductor from '@src/components/BannerConductor/FallbackBannerConductor.vue';
import Banner from './components/BannerVar.vue';
Expand Down
13 changes: 10 additions & 3 deletions banners/desktop/C24_WMDE_Desktop_DE_23/components/BannerVar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@
<template #donation-form="{ formInteraction }: any">
<MultiStepDonation
:step-controllers="stepControllers"
@form-interaction="formInteraction"
:submit-callback="onSubmit"
:form-action-override="formAction"
@form-interaction="formInteraction"
>

<template #[FormStepNames.MainDonationFormStep]="{ pageIndex, submit, isCurrent, previous }: any">
<MainDonationForm :page-index="pageIndex" @submit="submit" :is-current="isCurrent" @previous="previous"/>
<MainDonationForm :page-index="pageIndex" @submit="submit" :is-current="isCurrent" :show-receipt-checkbox-below="minimumAmount" @previous="previous"/>
</template>

<template #[FormStepNames.UpgradeToYearlyFormStep]="{ pageIndex, submit, isCurrent, previous }: any">
Expand Down Expand Up @@ -88,7 +89,7 @@ import FundsModal from '@src/components/UseOfFunds/FundsModal.vue';
import BannerText from '../content/BannerText.vue';
import BannerSlides from '../content/BannerSlides.vue';
import MultiStepDonation from '@src/components/DonationForm/MultiStepDonation.vue';
import MainDonationForm from '@src/components/DonationForm/Forms/MainDonationForm.vue';
import MainDonationForm from './MainDonationFormReceiptAboveValue.vue';
import UpgradeToYearlyButtonForm from '@src/components/DonationForm/Forms/UpgradeToYearlyButtonForm.vue';
import KeenSlider from '@src/components/Slider/KeenSlider.vue';
import { useFormModel } from '@src/components/composables/useFormModel';
Expand All @@ -111,6 +112,10 @@ import { BannerSubmitOnReturnEvent } from '@src/tracking/events/BannerSubmitOnRe
import { Tracker } from '@src/tracking/Tracker';
import { useBannerHider } from '@src/components/composables/useBannerHider';
import BannerTitle from '@banners/desktop/C24_WMDE_Desktop_DE_15/content/BannerTitle.vue';
import { useFormAction } from '../useFormAction';
import { FormActions } from '@src/domain/FormActions';
const minimumAmount = 10;
enum ContentStates {
Main = 'wmde-banner-wrapper--main',
Expand Down Expand Up @@ -143,6 +148,8 @@ const stepControllers = [
createSubmittableUpgradeToYearly( formModel, FormStepNames.MainDonationFormStep, FormStepNames.MainDonationFormStep )
];
const { formAction } = useFormAction( inject<FormActions>( 'formActions' ), minimumAmount );
watch( contentState, async () => {
emit( 'bannerContentChanged' );
} );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<button class="wmde-banner-form-button t-submit-main-donation" type="submit">
{{ submitButtonLabel }}
</button>
</template>

<script setup lang="ts">
import { computed, inject } from 'vue';
import { PaymentMethods } from '@src/utils/FormItemsBuilder/fields/PaymentMethods';
import { useFormModel } from '@src/components/composables/useFormModel';
import { Translator } from '@src/Translator';
import { AddressTypes } from '@src/utils/FormItemsBuilder/fields/AddressTypes';
const formModel = useFormModel();
const translator = inject<Translator>( 'translator' );
const { paymentMethod, addressType, receipt } = formModel;
const submitButtonLabel = computed( (): string => {
if ( !receipt.value && [ AddressTypes.ANONYMOUS.value, '' ].includes( addressType.value ) ) {
if ( paymentMethod.value === PaymentMethods.PAYPAL.value ) {
return translator.translate( 'submit-label-paypal' );
} else if ( paymentMethod.value === PaymentMethods.CREDIT_CARD.value ) {
return translator.translate( 'submit-label-credit-card' );
} else if ( paymentMethod.value === PaymentMethods.SOFORT.value ) {
return translator.translate( 'submit-label-sofort' );
} else if ( paymentMethod.value === PaymentMethods.BANK_TRANSFER.value ) {
return translator.translate( 'submit-label-bank-transfer' );
}
}
return translator.translate( 'submit-label' );
} );
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<template>
<form
method="post"
class="wmde-banner-sub-form wmde-banner-sub-form-donation"
@submit.prevent="validate"
>
<fieldset class="wmde-banner-form-field-group">
<legend class="wmde-banner-form-field-group-legend">{{ $translate( 'intervals-header' ) }}</legend>
<SelectGroup
:field-name="'select-interval'"
:selectionItems="formItems.intervals"
:isValid="isValidOrUnset( intervalValidity )"
:errorMessage="$translate( 'no-interval-message' )"
v-model:inputValue="interval"
:disabledOptions="disabledIntervals"
/>
</fieldset>

<fieldset class="wmde-banner-form-field-group">
<legend class="wmde-banner-form-field-group-legend">{{ $translate( 'amounts-header' ) }}</legend>
<SelectGroup
fieldName="select-amount"
:selectionItems="formItems.amounts"
:isValid="isValidOrUnset( amountValidity )"
:errorMessage="$translate( amountValidityMessageKey( amountValidity ) )"
v-model:inputValue="selectedAmount"
>
<SelectCustomAmount
fieldName="select-amount"
v-model:inputValue="customAmount"
@focus="clearSelectedAmount"
@blur="formatCustomAmount"
:placeholder="$translate( customAmountPlaceholderKey )"
/>
</SelectGroup>
</fieldset>

<fieldset class="wmde-banner-form-field-group">
<legend class="wmde-banner-form-field-group-legend">{{ $translate( 'payments-header' ) }}</legend>
<SelectGroup
:field-name="'select-payment-method'"
:selectionItems="formItems.paymentMethods"
:isValid="isValidOrUnset( paymentMethodValidity )"
:errorMessage="$translate( 'no-payment-type-message' )"
v-model:inputValue="paymentMethod"
:disabledOptions="disabledPaymentMethods"
>
<template #select-group-label="{ label, slotName }: any">
<slot :name="'label-' + slotName" :label="label"/>
</template>
<SmsBox>
<template #sms-icon>
<slot name="sms-icon"/>
</template>
</SmsBox>
</SelectGroup>
</fieldset>

<div class="wmde-banner-form-donation-receipt-checkbox" v-if="showReceiptCheckbox">
<input
class="wmde-banner-form-field-checkbox"
type="checkbox"
value="person"
id="wmde-banner-form-donation-receipt"
v-model="receipt"
>
<label for="wmde-banner-form-donation-receipt">
{{ $translate( 'donation-receipt-checkbox-label' ) }}
</label>
</div>

<div class="wmde-banner-form-button-container">
<slot name="button">
<MainDonationFormButtonMultiStep/>
</slot>
<button v-if="!isFormValid && showErrorScrollLink" class="wmde-banner-form-button-error">
{{ $translate( 'global-error' ) }}
</button>
</div>
</form>
</template>

<script lang="ts">
// All form components must have names
export default {
name: 'MainDonationFormDonationReceipt'
};
</script>
<script setup lang="ts">
import { computed, inject, onMounted, ref, watch } from 'vue';
import SelectGroup from '@src/components/DonationForm/SubComponents/SelectGroup.vue';
import { DonationFormItems } from '@src/utils/FormItemsBuilder/DonationFormItems';
import SelectCustomAmount from '@src/components/DonationForm/SubComponents/SelectCustomAmount.vue';
import SmsBox from '@src/components/DonationForm/SubComponents/SmsBox.vue';
import { useFormModel } from '@src/components/composables/useFormModel';
import { newDonationFormValidator } from '@src/validation/DonationFormValidator';
import { amountValidityMessageKey } from '@src/utils/amountValidityMessageKey';
import { isValidOrUnset } from '@src/components/DonationForm/Forms/isValidOrUnset';
import { Currency } from '@src/utils/DynamicContent/formatters/Currency';
import MainDonationFormButtonMultiStep from './MainDonationFormPaymentsAndReceiptButton.vue';
import { AddressTypes } from '@src/utils/FormItemsBuilder/fields/AddressTypes';
import { PaymentMethods } from '@src/utils/FormItemsBuilder/fields/PaymentMethods';
interface Props {
showReceiptCheckboxBelow: number;
showErrorScrollLink?: boolean;
customAmountPlaceholderKey?: string;
}
const props = withDefaults( defineProps<Props>(), {
showErrorScrollLink: false,
customAmountPlaceholderKey: 'custom-amount-placeholder'
} );
const emit = defineEmits( [ 'submit' ] );
const currencyFormatter = inject<Currency>( 'currencyFormatter' );
const formItems = inject<DonationFormItems>( 'formItems' );
const formModel = useFormModel();
const validator = newDonationFormValidator( formModel );
const showReceiptCheckbox = computed<boolean>( () => {
if ( interval.value === '' ) {
return false;
}
if ( paymentMethod.value === '' || paymentMethod.value === PaymentMethods.DIRECT_DEBIT.value ) {
return false;
}
if ( numericAmount.value >= props.showReceiptCheckboxBelow ) {
return false;
}
return true;
} );
const isFormValid = ref<boolean>( true );
const validate = (): void => {
isFormValid.value = validator.validate();
if ( isFormValid.value ) {
emit( 'submit' );
}
};
const {
interval, intervalValidity, disabledIntervals,
selectedAmount, customAmount, numericAmount, amountValidity,
paymentMethod, paymentMethodValidity, disabledPaymentMethods,
addressType, receipt
} = formModel;
const clearSelectedAmount = (): void => {
selectedAmount.value = '';
};
const formatCustomAmount = (): void => {
if ( customAmount.value !== '' ) {
customAmount.value = currencyFormatter.customAmountInput( numericAmount.value );
}
};
watch( [ interval, paymentMethod, numericAmount ], () => {
if ( !showReceiptCheckbox.value ) {
receipt.value = false;
}
} );
onMounted( () => {
addressType.value = AddressTypes.ANONYMOUS.value;
} );
</script>
3 changes: 2 additions & 1 deletion banners/desktop/C24_WMDE_Desktop_DE_23/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ const messages: TranslationMessages = {
'upgrade-to-yearly-yes': 'Ja, ich spende {{amount}} jährlich',
'campaign-day-only-n-days': 'Heute sind es nur noch {{days}} Tage bis zum Ende unserer Spendenkampagne.',
'custom-amount-placeholder': 'Wahlbetrag',
'upgrade-to-yearly-header': 'Bitte spenden Sie {{amount}} jährlich!'
'upgrade-to-yearly-header': 'Bitte spenden Sie {{amount}} jährlich!',
'donation-receipt-checkbox-label': 'Bitte senden Sie mir eine steuerlich absetzbare Spendenbescheinigung an meine Postanschrift.'
};

export default messages;
60 changes: 60 additions & 0 deletions banners/desktop/C24_WMDE_Desktop_DE_23/styles/styles_var.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// This is the file where we import the theme-specific component styles
@use 'src/themes/Treedip/swatches/skin_default' with (
$slider: true,
$select-group: true,
$upgrade-to-yearly: true,
$fallback-banner: true,
$double-progress-bar: true,
$soft-close: true,
);
@use 'src/components/BannerConductor/banner-transition';
@use 'src/themes/UseOfFunds/swatches/skin_default' as uof-default;
@use 'Banner';
@use 'src/themes/UseOfFunds/UseOfFunds';
@use 'MainBanner' with (
$banner-height: 357px,
$form-width: 300px
);
@use 'src/themes/Treedip/defaults';
@use 'src/themes/Treedip/ButtonClose/ButtonClose';
@use 'src/themes/Treedip/ProgressBar/DoubleProgressBar';
@use 'src/themes/Treedip/DonationForm/DonationForm';
@use 'src/themes/Treedip/DonationForm/MultiStepDonation';
@use 'src/themes/Treedip/DonationForm/SubComponents/SelectGroup';
@use 'src/themes/Treedip/DonationForm/SubComponents/SelectGroupRadios';
@use 'src/themes/Treedip/DonationForm/SubComponents/SelectCustomAmountRadio';
@use 'src/themes/Treedip/DonationForm/SubComponents/SmsBox';
@use 'src/themes/Treedip/DonationForm/Forms/MainDonationFormDonationReceipt' with (
$padding: 14px 0 0
);
@use 'src/themes/Treedip/DonationForm/Forms/UpgradeToYearlyButtonForm' with (
$font-size: 14px
);
@use 'src/themes/Treedip/DonationForm/Forms/CustomAmountForm';
@use 'src/themes/Treedip/Footer/FooterAlreadyDonated';
@use 'src/themes/Treedip/Footer/SelectionInput';
@use 'src/themes/Treedip/Message/Message' with (
$slider-main-headline-font-size: 25px,
$message-header-padding-bottom: 8px,
$message-header-small-up-padding-bottom: 8px
);
@use 'src/themes/Treedip/SoftClose/SoftClose';
@use 'src/themes/Treedip/Slider/KeenSlider' with (
$slider-padding: 0
);

/**
* Fallback banner with "Fijitiv" theme
* All selectors in Fijitiv theme are prefixed with the ".wmde-banner-fallback" class selector,
so they override the "default" styles with the same selector
*/
@use 'FallbackBanner';
@use 'src/themes/Fijitiv/FallbackBanner/FallbackButton';
@use 'src/themes/Fijitiv/FallbackBanner/LargeFooter' with (
$fallback-large-footer-right-before-border-color: white
);
@use 'src/themes/Fijitiv/FallbackBanner/SmallFooter';
@use 'src/themes/Fijitiv/ProgressBar/ProgressBar' as FallbackProgressBar with (
$progress-bar-margin: 0 15px
);
@use 'src/themes/Fijitiv/Slider/KeenSlider' as FallbackSlider;
22 changes: 22 additions & 0 deletions banners/desktop/C24_WMDE_Desktop_DE_23/useFormAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FormActions } from '@src/domain/FormActions';
import { computed, Ref } from 'vue';
import { useFormModel } from '@src/components/composables/useFormModel';
import { PaymentMethods } from '@src/utils/FormItemsBuilder/fields/PaymentMethods';

export function useFormAction( formActions: FormActions, minimumAmount: number ): { formAction: Ref<string> } {
const formModel = useFormModel();
const formAction = computed( (): string => {

let URL: string = formActions.donateAnonymouslyAction;

if ( formModel.numericAmount.value >= minimumAmount || formModel.receipt.value || formModel.paymentMethod.value === PaymentMethods.DIRECT_DEBIT.value ) {
URL = formActions.donateWithAddressAction + '&ap=1';
}

return URL;
} );

return {
formAction
};
}
3 changes: 2 additions & 1 deletion src/components/DonationForm/SubComponents/SubmitValues.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<input type="hidden" name="amount" :value="formattedAmountForServer" />
<input type="hidden" name="interval" :value="interval" />
<input type="hidden" name="paymentType" :value="paymentMethod" />
<input type="hidden" name="receipt" :value="receipt" />
</div>
</template>

Expand All @@ -12,7 +13,7 @@
import { useFormModel } from '@src/components/composables/useFormModel';
import { computed } from 'vue';
const { addressType, totalNumericAmount, interval, paymentMethod } = useFormModel();
const { addressType, totalNumericAmount, interval, paymentMethod, receipt } = useFormModel();
const formattedAmountForServer = computed( (): number => {
return parseFloat( totalNumericAmount.value.toFixed( 2 ) ) * 100;
Expand Down
6 changes: 5 additions & 1 deletion src/components/composables/useFormModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const paymentMethodValidity = ref<Validity>( Validity.Unset );
const addressType = ref<string>( '' );
const addressTypeValidity = ref<Validity>( Validity.Unset );

const receipt = ref<boolean|null>( null );

const hasTransactionFee = ref<boolean>( false );

const disabledIntervals = computed( (): string[] => {
Expand Down Expand Up @@ -121,8 +123,10 @@ export function useFormModel(): FormModel {
paymentMethodValidity,
disabledPaymentMethods,
addressType,

addressTypeValidity,

receipt,

disabledAddressTypes,

hasTransactionFee,
Expand Down
Loading

0 comments on commit 3798196

Please sign in to comment.