Skip to content

Commit

Permalink
Feature: add campaign goal types for recurring donations (#7567)
Browse files Browse the repository at this point in the history
Co-authored-by: Glauber Silva <[email protected]>
  • Loading branch information
glaubersilva and glaubersilva authored Oct 14, 2024
1 parent 63219f8 commit 520f2a3
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 56 deletions.
1 change: 1 addition & 0 deletions src/Campaigns/Actions/LoadCampaignDetailsAssets.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function __invoke()
[
'adminUrl' => admin_url(),
'currency' => give_get_currency(),
'isRecurringEnabled' => defined('GIVE_RECURRING_VERSION') ? GIVE_RECURRING_VERSION : null,
]
);

Expand Down
2 changes: 2 additions & 0 deletions src/Campaigns/Actions/LoadCampaignsListTableAssets.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public function __invoke()
'adminUrl' => admin_url(),
'paymentMode' => give_is_test_mode(),
'pluginUrl' => GIVE_PLUGIN_URL,
'currency' => give_get_currency(),
'isRecurringEnabled' => defined('GIVE_RECURRING_VERSION') ? GIVE_RECURRING_VERSION : null,
]
);

Expand Down
2 changes: 1 addition & 1 deletion src/Campaigns/Migrations/Tables/CreateCampaignsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function run()
primary_color VARCHAR(7) NOT NULL,
secondary_color VARCHAR(7) NOT NULL,
campaign_goal INT UNSIGNED NOT NULL,
goal_type VARCHAR(12) NOT NULL DEFAULT 'amount',
goal_type VARCHAR(24) NOT NULL DEFAULT 'amount',
status VARCHAR(12) NOT NULL,
start_date DATETIME NULL,
end_date DATETIME NULL,
Expand Down
76 changes: 73 additions & 3 deletions src/Campaigns/Routes/RegisterCampaignRoutes.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,14 @@ public function getSchema(): array
'errorMessage' => esc_html__('Must be a number', 'give'),
],
'goalType' => [
'enum' => ['amount', 'donation', 'donors'],
'enum' => [
'amount',
'donations',
'donors',
'amountFromSubscriptions',
'subscriptions',
'donorsFromSubscriptions',
],
'description' => esc_html__('Campaign goal type', 'give'),
],
],
Expand All @@ -247,6 +254,27 @@ public function getSchema(): array
],
],
],
[
'if' => [
'properties' => [
'goalType' => [
'const' => 'donations',
],
],
],
'then' => [
'properties' => [
'goal' => [
'minimum' => 1,
],
],
'errorMessage' => [
'properties' => [
'goal' => esc_html__('Number of donations must be greater than 0', 'give'),
],
],
],
],
[
'if' => [
'properties' => [
Expand All @@ -272,7 +300,7 @@ public function getSchema(): array
'if' => [
'properties' => [
'goalType' => [
'const' => 'donation',
'const' => 'amountFromSubscriptions',
],
],
],
Expand All @@ -284,7 +312,49 @@ public function getSchema(): array
],
'errorMessage' => [
'properties' => [
'goal' => esc_html__('Number of donations must be greater than 0', 'give'),
'goal' => esc_html__('Goal recurring amount must be greater than 0', 'give'),
],
],
],
],
[
'if' => [
'properties' => [
'goalType' => [
'const' => 'subscriptions',
],
],
],
'then' => [
'properties' => [
'goal' => [
'minimum' => 1,
],
],
'errorMessage' => [
'properties' => [
'goal' => esc_html__('Number of recurring donations must be greater than 0', 'give'),
],
],
],
],
[
'if' => [
'properties' => [
'goalType' => [
'const' => 'donorsFromSubscriptions',
],
],
],
'then' => [
'properties' => [
'goal' => [
'minimum' => 1,
],
],
'errorMessage' => [
'properties' => [
'goal' => esc_html__('Number of recurring donors must be greater than 0', 'give'),
],
],
],
Expand Down
19 changes: 14 additions & 5 deletions src/Campaigns/ValueObjects/CampaignGoalType.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@
/**
* @unreleased
*
* @method static CampaignType AMOUNT()
* @method static CampaignType DONATION()
* @method static CampaignType DONORS()
* @method static CampaignGoalType AMOUNT()
* @method static CampaignGoalType DONATIONS()
* @method static CampaignGoalType DONORS()
* @method static CampaignGoalType AMOUNT_FROM_SUBSCRIPTIONS()
* @method static CampaignGoalType SUBSCRIPTIONS()
* @method static CampaignGoalType DONORS_FROM_SUBSCRIPTIONS()
* @method bool isAmount()
* @method bool isDonation()
* @method bool isDonations()
* @method bool isDonors()
* @method bool isAmountFromSubscriptions()
* @method bool isSubscriptions()
* @method bool isDonorsFromSubscriptions()
*/
class CampaignGoalType extends Enum
{
const AMOUNT = 'amount';
const DONATION = 'donation';
const DONATIONS = 'donations';
const DONORS = 'donors';
const AMOUNT_FROM_SUBSCRIPTIONS = 'amountFromSubscriptions';
const SUBSCRIPTIONS = 'subscriptions';
const DONORS_FROM_SUBSCRIPTIONS = 'donorsFromSubscriptions';
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,25 @@ export default () => {
switch (type) {
case 'amount':
return __(
'Your goal progress is measured by the total amount raised based on the goal amount. (e.g. $500 of $1,000 raised)',
'Your goal progress is measured by the total amount of funds raised eg. $500 of $1,000 raised.',
'give'
);
case 'donation':
return __('The total number of donations made for the campaign', 'give');
case 'donations':
return __('Your goal progress is measured by the number of donations. eg. 1 of 5 donations.', 'give');
case 'donors':
return __('The total number of unique donors who have donated to the campaign', 'give');
return __(
'Your goal progress is measured by the number of donors. eg. 10 of 50 donors have given.',
'give'
);
case 'amountFromSubscriptions':
return __('Only the first donation amount of a recurring donation is counted toward the goal.', 'give');
case 'subscriptions':
return __('Only the first donation of a recurring donation is counted toward the goal.', 'give');
case 'donorsFromSubscriptions':
return __(
'Only the donors that subscribed to a recurring donation are counted toward the goal.',
'give'
);
default:
return null;
}
Expand Down Expand Up @@ -66,7 +78,9 @@ export default () => {
</div>

{isDisabled ? (
<textarea disabled={true} rows={10}>{shortDescription.replace(/(<([^>]+)>)/gi, '')}</textarea>
<textarea disabled={true} rows={10}>
{shortDescription.replace(/(<([^>]+)>)/gi, '')}
</textarea>
) : (
<Editor name="shortDescription" />
)}
Expand Down Expand Up @@ -116,8 +130,19 @@ export default () => {

<select {...register('goalType')} disabled={isDisabled}>
<option value="amount">{__('Amount raised', 'give')}</option>
<option value="donation">{__('Number of Donations', 'give')}</option>
<option value="donors">{__('Number of Donors', 'give')}</option>
<option value="donations">{__('Number of donations', 'give')}</option>
<option value="donors">{__('Number of donors', 'give')}</option>
{window.GiveCampaignDetails.isRecurringEnabled && (
<>
<option value="amountFromSubscriptions">
{__('Recurring amount raised', 'give')}
</option>
<option value="subscriptions">{__('Number of recurring donations', 'give')}</option>
<option value="donorsFromSubscriptions">
{__('Number of recurring donors', 'give')}
</option>
</>
)}
</select>

<div className={styles.sectionFieldDescription}>{goalDescription(goalType)}</div>
Expand All @@ -130,7 +155,7 @@ export default () => {
{__('Let us know the target amount you’re aiming for in your campaign.', 'give')}
</div>

{goalType === 'amount' ? (
{goalType === 'amount' || goalType === 'amountFromSubscriptions' ? (
<Currency name="goal" currency={window.GiveCampaignDetails.currency} disabled={isDisabled} />
) : (
<input type="number" {...register('goal', {valueAsNumber: true})} disabled={isDisabled} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {FC} from 'react';
export interface GiveCampaignDetails {
adminUrl: string;
currency: string;
isRecurringEnabled: boolean;
}

export type CampaignDetailsTab = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,12 @@

.goalTypeOptionIcon {

svg {
width: 2.5rem;
height: 2.5rem;
}
line-height: 0.875rem;
margin-top: 0.175rem;

path {
stroke: #9CA0AF;
svg {
width: 1.5rem;
height: 1.5rem;
}
}

Expand All @@ -57,9 +56,14 @@
cursor: pointer;
}

span {
> label {
font-size: 0.875rem !important;
}

> span {
font-size: 0.75rem !important;
margin-top: 0.2rem;
display: inline-block;
display: none;
line-height: 1rem !important;
}

Expand All @@ -77,16 +81,25 @@
background-color: #374151;

.goalTypeOptionIcon {
svg path {

svg path:not([fill]) {
stroke: #F9FAFB;
}

svg path:not([stroke]) {
fill: #F9FAFB;
}
}

.goalTypeOptionText {
label,
span {
color: #F9FAFB !important;
}

span {
display: inline-block;
}
}
}
}
Expand Down
Loading

0 comments on commit 520f2a3

Please sign in to comment.