PluginProbe
Ultimate Store Kit / 3.1.0
Ultimate Store Kit v3.1.0
3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.0.7 3.0.5 3.0.4 3.0.3 3.0.2 trunk 1.5.0 1.5.1 1.5.2 1.6.1 1.6.2 1.6.3 1.6.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 92 releases
ultimate-store-kit / src / admin / pages / License.js

License.js in Ultimate Store Kit 3.1.0, at src/admin/pages/License.js

443 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useEffect, useState } from '@wordpress/element';
2 import { __ } from '@wordpress/i18n';
3 import { CheckIcon, CloseIcon } from '../icons';
4 import { btnPrimary, btnSecondary, licenseInput } from '../tw';
5
6 const adminData = window.ultimateStoreKitAdminData || {};
7
8 const getRestHeaders = () => ({
9 'Content-Type': 'application/json',
10 'X-WP-Nonce': adminData.restNonce,
11 });
12
13 const msgBar =
14 'animate-usk-slide-in mb-5 flex items-center justify-between rounded-lg px-4 py-2.5 text-[13px] font-medium';
15
16 const License = ({ isPro, onLicenseStatusChange }) => {
17 const initialLicenseData = adminData.licenseData || {};
18
19 const [licenseData, setLicenseData] = useState(initialLicenseData);
20 const [licenseKey, setLicenseKey] = useState('');
21 const [licenseEmail, setLicenseEmail] = useState(
22 initialLicenseData.license_email || ''
23 );
24 const [loading, setLoading] = useState(false);
25 const [message, setMessage] = useState(
26 initialLicenseData.show_message
27 ? {
28 type: 'error',
29 text: initialLicenseData.license_message || '',
30 }
31 : null
32 );
33
34 const isActivated = licenseData.is_activated || false;
35
36 useEffect(() => {
37 if (!adminData.restUrl) {
38 return;
39 }
40
41 fetch(`${adminData.restUrl}license/status`, {
42 method: 'GET',
43 headers: getRestHeaders(),
44 })
45 .then((res) => res.json())
46 .then((response) => {
47 if (response.success && response.license_data) {
48 setLicenseData(response.license_data);
49 setLicenseEmail(response.license_data.license_email || '');
50 if (onLicenseStatusChange) {
51 onLicenseStatusChange(true);
52 }
53 } else if (response.error_message) {
54 if (onLicenseStatusChange) {
55 onLicenseStatusChange(false);
56 }
57 setMessage({
58 type: 'error',
59 text: response.error_message,
60 });
61 }
62 })
63 .catch(() => {});
64 }, []);
65
66 const handleActivate = (e) => {
67 e.preventDefault();
68
69 if (!licenseKey || !licenseEmail) {
70 setMessage({
71 type: 'error',
72 text: __(
73 'Please provide both license key and email address.',
74 'ultimate-store-kit'
75 ),
76 });
77 return;
78 }
79
80 setLoading(true);
81 setMessage(null);
82
83 fetch(`${adminData.restUrl}license/activate`, {
84 method: 'POST',
85 headers: getRestHeaders(),
86 body: JSON.stringify({
87 license_key: licenseKey,
88 email: licenseEmail,
89 }),
90 })
91 .then((res) => res.json())
92 .then((response) => {
93 if (response.success) {
94 setLicenseData(response.license_data);
95 if (onLicenseStatusChange) {
96 onLicenseStatusChange(true);
97 }
98 setMessage({
99 type: 'success',
100 text:
101 response.message ||
102 __(
103 'License activated successfully!',
104 'ultimate-store-kit'
105 ),
106 });
107 setLicenseKey('');
108 } else {
109 if (onLicenseStatusChange) {
110 onLicenseStatusChange(false);
111 }
112 setMessage({
113 type: 'error',
114 text:
115 response.message ||
116 __(
117 'License activation failed.',
118 'ultimate-store-kit'
119 ),
120 });
121 }
122 })
123 .catch(() => {
124 setMessage({
125 type: 'error',
126 text: __(
127 'An error occurred. Please try again.',
128 'ultimate-store-kit'
129 ),
130 });
131 })
132 .finally(() => {
133 setLoading(false);
134 });
135 };
136
137 const handleDeactivate = () => {
138 if (
139 !window.confirm(
140 __(
141 'Are you sure you want to deactivate the license?',
142 'ultimate-store-kit'
143 )
144 )
145 ) {
146 return;
147 }
148
149 setLoading(true);
150 setMessage(null);
151
152 fetch(`${adminData.restUrl}license/deactivate`, {
153 method: 'DELETE',
154 headers: getRestHeaders(),
155 })
156 .then((res) => res.json())
157 .then((response) => {
158 if (response.success) {
159 setLicenseData({});
160 if (onLicenseStatusChange) {
161 onLicenseStatusChange(false);
162 }
163 setLicenseEmail('');
164 setLicenseKey('');
165 setMessage({
166 type: 'success',
167 text:
168 response.message ||
169 __(
170 'License deactivated successfully.',
171 'ultimate-store-kit'
172 ),
173 });
174 } else {
175 setMessage({
176 type: 'error',
177 text:
178 response.message ||
179 __(
180 'Failed to deactivate license.',
181 'ultimate-store-kit'
182 ),
183 });
184 }
185 })
186 .catch(() => {
187 setMessage({
188 type: 'error',
189 text: __(
190 'An error occurred. Please try again.',
191 'ultimate-store-kit'
192 ),
193 });
194 })
195 .finally(() => {
196 setLoading(false);
197 });
198 };
199
200 return (
201 <div className="">
202 <div className="mb-4 rounded-lg border border-solid border-gray-100 bg-white p-8">
203 <div className="mb-6 border-0 border-b border-solid border-b-gray-100 pb-4">
204 <h2 className="m-0 mb-1 text-xl font-bold text-slate-800">
205 {isActivated
206 ? __(
207 'Ultimate Store Kit License Info',
208 'ultimate-store-kit'
209 )
210 : __(
211 'Activate Your License',
212 'ultimate-store-kit'
213 )}
214 </h2>
215 <p className="m-0 text-[14px] leading-relaxed text-slate-500">
216 {isActivated
217 ? __(
218 'Your license is active. View details and manage your subscription below.',
219 'ultimate-store-kit'
220 )
221 : __(
222 'Enter your license key to activate and receive updates & premium support.',
223 'ultimate-store-kit'
224 )}
225 </p>
226 </div>
227
228 {message && (
229 <div
230 className={`${msgBar} ${
231 message.type === 'success'
232 ? 'border border-emerald-200 bg-emerald-100 text-emerald-800'
233 : 'border border-red-200 bg-red-100 text-red-900'
234 }`}
235 >
236 <span>{message.text}</span>
237 <button
238 type="button"
239 onClick={() => setMessage(null)}
240 className="cursor-pointer border-0 bg-transparent px-1 text-lg leading-none text-inherit"
241 >
242 &times;
243 </button>
244 </div>
245 )}
246
247 {isActivated ? (
248 <div className="block">
249 <div className="mb-5">
250 <div className="flex flex-col gap-4">
251 <div className="flex flex-col gap-2 border-0 border-b border-solid border-b-gray-100 pb-4">
252 <span className="text-[14px] font-semibold text-slate-600">
253 {__('Status', 'ultimate-store-kit')}
254 </span>
255 <span
256 className={`inline-flex items-center gap-2 self-start rounded-[10px] px-3 py-1 text-xs font-bold ${
257 licenseData.is_valid
258 ? 'border border-emerald-200 bg-emerald-100 text-emerald-800'
259 : 'border border-red-200 bg-red-100 text-red-900'
260 }`}
261 >
262 {licenseData.is_valid ? (
263 <CheckIcon className="h-[14px] w-[14px]" />
264 ) : (
265 <CloseIcon className="h-[14px] w-[14px]" />
266 )}
267 {licenseData.is_valid
268 ? __(
269 'Valid',
270 'ultimate-store-kit'
271 )
272 : __(
273 'Invalid',
274 'ultimate-store-kit'
275 )}
276 </span>
277 </div>
278
279 {licenseData.license_title && (
280 <div className="flex flex-col gap-1 border-0 border-b border-solid border-b-gray-100 pb-4">
281 <span className="text-[14px] font-semibold text-slate-600">
282 {__(
283 'License Type',
284 'ultimate-store-kit'
285 )}
286 </span>
287 <span className="text-[14px] text-slate-800">
288 {licenseData.license_title}
289 </span>
290 </div>
291 )}
292
293 {licenseData.expire_date && (
294 <div className="flex flex-col gap-1 border-0 border-b border-solid border-b-gray-100 pb-4">
295 <span className="text-[14px] font-semibold text-slate-600">
296 {__(
297 'License Expired on',
298 'ultimate-store-kit'
299 )}
300 </span>
301 <span className="text-[14px] text-slate-800">
302 {licenseData.expire_date}
303 </span>
304 </div>
305 )}
306
307 {licenseData.support_end && (
308 <div className="flex flex-col gap-1 border-0 border-b border-solid border-b-gray-100 pb-4">
309 <span className="text-[14px] font-semibold text-slate-600">
310 {__(
311 'Support Expired on',
312 'ultimate-store-kit'
313 )}
314 </span>
315 <span className="text-[14px] text-slate-800">
316 {licenseData.support_end}
317 </span>
318 </div>
319 )}
320
321 {licenseData.masked_key && (
322 <div className="flex flex-col gap-2 pb-4">
323 <span className="text-[14px] font-semibold text-slate-600">
324 {__(
325 'Your License Key',
326 'ultimate-store-kit'
327 )}
328 </span>
329 <span className="inline-flex w-fit max-w-full items-center rounded-md border border-slate-200 bg-slate-50 px-3 py-2 font-mono text-[12px] text-slate-700">
330 {licenseData.masked_key}
331 </span>
332 </div>
333 )}
334 </div>
335
336 <button
337 type="button"
338 onClick={handleDeactivate}
339 disabled={loading}
340 className="mt-4 inline-flex items-center justify-center rounded-md border border-solid border-slate-300 bg-white px-4 py-2 text-sm font-semibold text-slate-700 cursor-pointer transition-colors hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-60"
341 >
342 {loading
343 ? __(
344 'Deactivating...',
345 'ultimate-store-kit'
346 )
347 : __(
348 'Deactivate License',
349 'ultimate-store-kit'
350 )}
351 </button>
352 </div>
353 </div>
354 ) : (
355 <div className="mt-0">
356 <form onSubmit={handleActivate} className="flex flex-col gap-5">
357 <div className="flex flex-col gap-1.5">
358 <label
359 htmlFor="usk-license-key"
360 className="text-[13px] font-semibold text-slate-700"
361 >
362 {__('License Code', 'ultimate-store-kit')}
363 </label>
364 <input
365 type="text"
366 id="usk-license-key"
367 className={licenseInput}
368 value={licenseKey}
369 onChange={(e) =>
370 setLicenseKey(e.target.value)
371 }
372 placeholder="xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx"
373 required
374 />
375 </div>
376
377 <div className="flex flex-col gap-1.5">
378 <label
379 htmlFor="usk-license-email"
380 className="text-[13px] font-semibold text-slate-700"
381 >
382 {__('Email Address', 'ultimate-store-kit')}
383 </label>
384 <input
385 type="email"
386 id="usk-license-email"
387 className={licenseInput}
388 value={licenseEmail}
389 onChange={(e) =>
390 setLicenseEmail(e.target.value)
391 }
392 placeholder="example@email.com"
393 required
394 />
395 </div>
396
397 <p className="m-0 text-[12px] leading-relaxed text-slate-500">
398 {__(
399 'We will send update news of this product by this email address, don\'t worry, we hate spam.',
400 'ultimate-store-kit'
401 )}
402 </p>
403
404 <div className="mt-1 flex items-center gap-3">
405 <button
406 type="submit"
407 disabled={loading}
408 className={`${btnPrimary} rounded-md inline-flex items-center justify-center`}
409 >
410 {loading
411 ? __(
412 'Activating...',
413 'ultimate-store-kit'
414 )
415 : __(
416 'Activate License',
417 'ultimate-store-kit'
418 )}
419 </button>
420 {!isPro && (
421 <a
422 href="https://storekit.pro/pricing/"
423 target="_blank"
424 rel="noopener noreferrer"
425 className={btnSecondary}
426 >
427 {__(
428 'Get Pro License',
429 'ultimate-store-kit'
430 )}
431 </a>
432 )}
433 </div>
434 </form>
435 </div>
436 )}
437 </div>
438 </div>
439 );
440 };
441
442 export default License;
443