PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.2.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.2.1
2.4.1 2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 All 68 releases
better-payment / src / campaign-list / TemplateSelectModal.js

TemplateSelectModal.js in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.2.1, at src/campaign-list/TemplateSelectModal.js

144 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useState } from '@wordpress/element';
2 import { __ } from '@wordpress/i18n';
3
4 const TEMPLATE_ICONS = {
5 'blank-1col': (
6 <svg width="64" height="48" viewBox="0 0 64 48" fill="none" xmlns="http://www.w3.org/2000/svg">
7 <rect x="4" y="4" width="56" height="40" rx="3" fill="#f0f0f1" stroke="#ddd" strokeWidth="1.5"/>
8 <rect x="10" y="10" width="44" height="6" rx="2" fill="#6b63f6" opacity="0.6"/>
9 <rect x="10" y="20" width="44" height="4" rx="2" fill="#ddd"/>
10 <rect x="10" y="28" width="34" height="4" rx="2" fill="#ddd"/>
11 <rect x="10" y="36" width="20" height="4" rx="2" fill="#ddd"/>
12 </svg>
13 ),
14 'blank-2col': (
15 <svg width="64" height="48" viewBox="0 0 64 48" fill="none" xmlns="http://www.w3.org/2000/svg">
16 <rect x="4" y="4" width="56" height="40" rx="3" fill="#f0f0f1" stroke="#ddd" strokeWidth="1.5"/>
17 <rect x="8" y="10" width="30" height="6" rx="2" fill="#6b63f6" opacity="0.6"/>
18 <rect x="8" y="20" width="30" height="4" rx="2" fill="#ddd"/>
19 <rect x="8" y="28" width="24" height="4" rx="2" fill="#ddd"/>
20 <rect x="8" y="36" width="16" height="4" rx="2" fill="#ddd"/>
21 <rect x="42" y="10" width="14" height="28" rx="2" fill="#6b63f6" opacity="0.15" stroke="#6b63f6" strokeWidth="1"/>
22 </svg>
23 ),
24 'blank-3col': (
25 <svg width="64" height="48" viewBox="0 0 64 48" fill="none" xmlns="http://www.w3.org/2000/svg">
26 <rect x="4" y="4" width="56" height="40" rx="3" fill="#f0f0f1" stroke="#ddd" strokeWidth="1.5"/>
27 <rect x="7" y="10" width="15" height="28" rx="2" fill="#6b63f6" opacity="0.15" stroke="#6b63f6" strokeWidth="1"/>
28 <rect x="25" y="10" width="15" height="28" rx="2" fill="#6b63f6" opacity="0.15" stroke="#6b63f6" strokeWidth="1"/>
29 <rect x="43" y="10" width="15" height="28" rx="2" fill="#6b63f6" opacity="0.15" stroke="#6b63f6" strokeWidth="1"/>
30 </svg>
31 ),
32 'charity-basic': (
33 <svg width="64" height="48" viewBox="0 0 64 48" fill="none" xmlns="http://www.w3.org/2000/svg">
34 <rect x="4" y="4" width="56" height="40" rx="3" fill="#f0f0f1" stroke="#ddd" strokeWidth="1.5"/>
35 <rect x="8" y="8" width="30" height="16" rx="2" fill="#6b63f6" opacity="0.3"/>
36 <rect x="8" y="28" width="30" height="4" rx="2" fill="#6b63f6" opacity="0.6"/>
37 <rect x="8" y="36" width="22" height="4" rx="2" fill="#ddd"/>
38 <rect x="42" y="8" width="14" height="8" rx="2" fill="#ddd"/>
39 <rect x="42" y="20" width="14" height="4" rx="2" fill="#ddd"/>
40 <rect x="42" y="28" width="14" height="4" rx="2" fill="#ddd"/>
41 <rect x="42" y="36" width="14" height="4" rx="2" fill="#6b63f6" opacity="0.7"/>
42 </svg>
43 ),
44 };
45
46 export default function TemplateSelectModal( { onClose } ) {
47 const data = window.betterPaymentCampaignData || {};
48 const adminData = window.betterPaymentAdmin || {};
49 const templates = data.templates || adminData.campaignTemplates || [];
50 const restUrl = data.restUrl || adminData.apiUrl || '';
51 const nonce = data.nonce || adminData.nonce || '';
52 const adminUrl = data.adminUrl || adminData.adminBaseUrl || '';
53 const [ creating, setCreating ] = useState( false );
54 const [ error, setError ] = useState( null );
55
56 const handleSelect = async ( template ) => {
57 setCreating( true );
58 setError( null );
59
60 try {
61 const res = await fetch( `${ restUrl }campaigns`, {
62 method: 'POST',
63 headers: {
64 'Content-Type': 'application/json',
65 'X-WP-Nonce': nonce,
66 },
67 body: JSON.stringify( {
68 title: template.default_title || template.label || __( 'New Campaign', 'better-payment' ),
69 post_status: 'draft',
70 bpc_fields_layout: JSON.stringify( {
71 layout: template.layout,
72 columns: template.columns,
73 } ),
74 } ),
75 } );
76
77 if ( ! res.ok ) {
78 throw new Error( __( 'Could not create campaign. Please try again.', 'better-payment' ) );
79 }
80
81 const campaign = await res.json();
82 window.location.href = `${ adminUrl }admin.php?page=bp-campaign-builder&campaign_id=${ campaign.id }`;
83 } catch ( err ) {
84 setError( err.message );
85 setCreating( false );
86 }
87 };
88
89 const handleOverlayClick = ( e ) => {
90 if ( e.target === e.currentTarget ) {
91 onClose();
92 }
93 };
94
95 return (
96 <div className="bp-template-modal-overlay" onClick={ handleOverlayClick }>
97 <div className="bp-template-modal">
98 <div className="bp-template-modal__header">
99 <h2>{ __( 'Choose a Starting Layout', 'better-payment' ) }</h2>
100 <p>{ __( 'Select a template to begin building your fundraising campaign.', 'better-payment' ) }</p>
101 <button
102 className="bp-template-modal__close"
103 onClick={ onClose }
104 aria-label={ __( 'Close', 'better-payment' ) }
105 >
106 ✕
107 </button>
108 </div>
109
110 { error && (
111 <div className="bp-template-modal__error">{ error }</div>
112 ) }
113
114 { creating ? (
115 <div className="bp-template-modal__loading">
116 <span className="spinner is-active" style={ { float: 'none', margin: '0 8px 0 0' } } />
117 { __( 'Creating campaign…', 'better-payment' ) }
118 </div>
119 ) : (
120 <div className="bp-template-modal__grid">
121 { templates.map( ( tpl ) => (
122 <button
123 key={ tpl.key }
124 className="bp-template-card"
125 onClick={ () => handleSelect( tpl ) }
126 >
127 <div className="bp-template-card__thumb">
128 { TEMPLATE_ICONS[ tpl.key ] || (
129 <span className="dashicons dashicons-layout" />
130 ) }
131 </div>
132 <div className="bp-template-card__info">
133 <strong>{ tpl.label }</strong>
134 <span>{ tpl.description }</span>
135 </div>
136 </button>
137 ) ) }
138 </div>
139 ) }
140 </div>
141 </div>
142 );
143 }
144