appscms-tools-theme 5.2.2 → 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/_data/feature/en/3_shop_posters.json +456 -1
- data/_data/home/en/ens.json +4 -4
- data/_data/templates.json +17459 -0
- data/_data/vintage/en/test.json +142 -0
- data/_includes/.DS_Store +0 -0
- data/_includes/appscms/footer/ai-image-tools-footer.html +14 -0
- data/_includes/appscms/head/head.html +61 -36
- data/_includes/appscms/headings/ai-image-tools-headings.html +24 -0
- data/_includes/appscms/navbars/ai-image-tools-navbar.html +446 -0
- data/_includes/appscms/scripts/script.html +17 -3
- data/_layouts/ai-image-generator.html +307 -0
- data/_layouts/ai-image-home.html +160 -0
- data/_layouts/ai-image-pricing.html +366 -0
- data/assets/css/ai-image-generator.css +547 -0
- data/assets/css/ai-image-home.css +760 -0
- data/assets/css/appscms-variables.css +1 -1
- data/assets/js/appscms-login.js +1 -1
- data/assets/js/get-credits.js +91 -0
- metadata +13 -2
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
{%- include appscms/head/head.html -%}
|
|
4
|
+
|
|
5
|
+
<style>
|
|
6
|
+
.pricing-container {
|
|
7
|
+
max-width: 1400px;
|
|
8
|
+
margin: 0 auto;
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
11
|
+
gap: 30px;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.pricing-card {
|
|
16
|
+
background: white;
|
|
17
|
+
border-radius: 20px;
|
|
18
|
+
padding: 40px 30px;
|
|
19
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
|
|
20
|
+
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|
21
|
+
position: relative;
|
|
22
|
+
border: 2px solid #e8ecf1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.pricing-card:hover {
|
|
26
|
+
transform: translateY(-10px);
|
|
27
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.pricing-card.popular {
|
|
31
|
+
border: 3px solid #f59e0b;
|
|
32
|
+
box-shadow: 0 15px 50px rgba(245, 158, 11, 0.2);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.popular-badge {
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: -15px;
|
|
38
|
+
right: 30px;
|
|
39
|
+
background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
|
|
40
|
+
color: white;
|
|
41
|
+
padding: 8px 20px;
|
|
42
|
+
border-radius: 20px;
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.plan-header {
|
|
49
|
+
margin-bottom: 30px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.plan-name {
|
|
53
|
+
text-align: left;
|
|
54
|
+
font-size: 28px;
|
|
55
|
+
font-weight: 700;
|
|
56
|
+
color: #1f2937;
|
|
57
|
+
margin-bottom: 8px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.plan-description {
|
|
61
|
+
color: #6b7280;
|
|
62
|
+
font-size: 14px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.price-section {
|
|
66
|
+
margin-bottom: 30px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.price {
|
|
70
|
+
font-size: 48px;
|
|
71
|
+
font-weight: 800;
|
|
72
|
+
color: #1f2937;
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: baseline;
|
|
75
|
+
gap: 5px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.original-price {
|
|
79
|
+
font-size: 18px;
|
|
80
|
+
color: #9ca3af;
|
|
81
|
+
text-decoration: line-through;
|
|
82
|
+
font-weight: 500;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.period {
|
|
86
|
+
font-size: 16px;
|
|
87
|
+
color: #6b7280;
|
|
88
|
+
font-weight: 400;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.buy-button {
|
|
92
|
+
width: 100%;
|
|
93
|
+
padding: 16px;
|
|
94
|
+
background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
|
|
95
|
+
color: white;
|
|
96
|
+
border: none;
|
|
97
|
+
border-radius: 12px;
|
|
98
|
+
font-size: 16px;
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
transition: all 0.3s ease;
|
|
102
|
+
margin-bottom: 30px;
|
|
103
|
+
box-shadow: 0 4px 15px rgba(245, 158, 11, 0.3);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.buy-button:hover {
|
|
107
|
+
transform: scale(1.02);
|
|
108
|
+
box-shadow: 0 6px 20px rgba(245, 158, 11, 0.4);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.features-list {
|
|
112
|
+
list-style: none;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.feature-item {
|
|
116
|
+
display: flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
gap: 12px;
|
|
119
|
+
margin-bottom: 16px;
|
|
120
|
+
color: #374151;
|
|
121
|
+
font-size: 14px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.checkmark {
|
|
125
|
+
width: 24px;
|
|
126
|
+
height: 24px;
|
|
127
|
+
border-radius: 50%;
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
justify-content: center;
|
|
131
|
+
flex-shrink: 0;
|
|
132
|
+
font-size: 12px;
|
|
133
|
+
font-weight: 700;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.checkmark.active {
|
|
137
|
+
background: #10b981;
|
|
138
|
+
color: white;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.checkmark.inactive {
|
|
142
|
+
background: #ef4444;
|
|
143
|
+
color: white;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.feature-item.highlighted {
|
|
147
|
+
color: #f59e0b;
|
|
148
|
+
font-weight: 600;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@media (max-width: 768px) {
|
|
152
|
+
.pricing-container {
|
|
153
|
+
grid-template-columns: 1fr;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
</style>
|
|
157
|
+
|
|
158
|
+
<body>
|
|
159
|
+
<div class="container">
|
|
160
|
+
{%- include /appscms/navbars/ai-image-tools-navbar.html -%}
|
|
161
|
+
|
|
162
|
+
<center>
|
|
163
|
+
<h1 class="appscms-h1">Pricing & Plans</h1>
|
|
164
|
+
<h2 class="appscms-h2"> Choose the subscription plan that fits you and unlock Nano Banana images.
|
|
165
|
+
</h2>
|
|
166
|
+
</center>
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
<div class="pricing-container" id="pricingContainer"></div>
|
|
170
|
+
|
|
171
|
+
{%- include /appscms/footer/ai-image-tools-footer.html -%}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
{%- include /appscms/scripts/script.html -%}
|
|
178
|
+
|
|
179
|
+
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
|
|
180
|
+
|
|
181
|
+
<script>
|
|
182
|
+
async function getAuthToken() {
|
|
183
|
+
const storedToken = localStorage.getItem("authToken");
|
|
184
|
+
if (storedToken) return storedToken;
|
|
185
|
+
|
|
186
|
+
if (typeof firebase !== "undefined" && firebase.auth) {
|
|
187
|
+
try {
|
|
188
|
+
const user = firebase.auth().currentUser;
|
|
189
|
+
if (user) {
|
|
190
|
+
const token = await user.getIdToken(true);
|
|
191
|
+
localStorage.setItem("authToken", token);
|
|
192
|
+
return token;
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.warn("Firebase auth error:", error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return sessionStorage.getItem("authToken") || null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function loadPricingPlans() {
|
|
203
|
+
try {
|
|
204
|
+
const res = await fetch(
|
|
205
|
+
"https://us-central1-appscms-develop.cloudfunctions.net/payment_api/api/v1/payment-routes/image-toolkit-plans"
|
|
206
|
+
);
|
|
207
|
+
const data = await res.json();
|
|
208
|
+
|
|
209
|
+
const container = document.getElementById("pricingContainer");
|
|
210
|
+
container.innerHTML = "";
|
|
211
|
+
|
|
212
|
+
data.plans.forEach((plan, index) => {
|
|
213
|
+
const features = plan.description
|
|
214
|
+
.replace(/"/g, "")
|
|
215
|
+
.split(",")
|
|
216
|
+
.map(item => item.trim());
|
|
217
|
+
|
|
218
|
+
const isPopular = plan.plan.toLowerCase() === "pro";
|
|
219
|
+
|
|
220
|
+
const card = `
|
|
221
|
+
<div class="pricing-card ${isPopular ? "popular" : ""}">
|
|
222
|
+
${isPopular ? `<span class="popular-badge">Most Popular</span>` : ""}
|
|
223
|
+
|
|
224
|
+
<div class="plan-header">
|
|
225
|
+
<h2 class="plan-name">${plan.plan}</h2>
|
|
226
|
+
<p class="plan-description">
|
|
227
|
+
${isPopular ? "For creators and professionals" : "Perfect for beginners"}
|
|
228
|
+
</p>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<div class="price-section">
|
|
232
|
+
<div class="price">
|
|
233
|
+
$${plan.price_dollar}
|
|
234
|
+
<span class="period">/month</span>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<button class="buy-button"
|
|
239
|
+
onclick="buyPlan('${plan.razorpay_plan_id}', '${plan.plan}')">
|
|
240
|
+
Buy Now
|
|
241
|
+
</button>
|
|
242
|
+
|
|
243
|
+
<ul class="features-list">
|
|
244
|
+
${features.map(f => `
|
|
245
|
+
<li class="feature-item">
|
|
246
|
+
<span class="checkmark active">✓</span>
|
|
247
|
+
<span>${f}</span>
|
|
248
|
+
</li>
|
|
249
|
+
`).join("")}
|
|
250
|
+
</ul>
|
|
251
|
+
</div>
|
|
252
|
+
`;
|
|
253
|
+
|
|
254
|
+
container.insertAdjacentHTML("beforeend", card);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
} catch (err) {
|
|
258
|
+
console.error("Pricing load error:", err);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const PAYMENT_API_URL = "https://us-central1-appscms-develop.cloudfunctions.net/payment_api";
|
|
263
|
+
|
|
264
|
+
async function checkSubscriptionStatus(subscriptionId) {
|
|
265
|
+
const POLL_INTERVAL = 3000; // 3 sec (OK to keep)
|
|
266
|
+
const TIMEOUT = 2 * 60 * 1000; // 2 minutes max
|
|
267
|
+
|
|
268
|
+
const startTime = Date.now();
|
|
269
|
+
const authToken = await getAuthToken();
|
|
270
|
+
|
|
271
|
+
const poll = async () => {
|
|
272
|
+
try {
|
|
273
|
+
const res = await fetch(
|
|
274
|
+
`${PAYMENT_API_URL}/api/v1/payment-routes/subscription-status?subscription_id=${subscriptionId}`,
|
|
275
|
+
{
|
|
276
|
+
method: "GET",
|
|
277
|
+
headers: {
|
|
278
|
+
"Content-Type": "application/json",
|
|
279
|
+
"Authorization": `Bearer ${authToken}`,
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const data = await res.json();
|
|
285
|
+
console.log("Subscription status:", data.status);
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
// ✅ ACTIVE → STOP
|
|
289
|
+
if (data.status === "activated") {
|
|
290
|
+
alert("✅ Subscription Active!");
|
|
291
|
+
hideLoadingOverlay()
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
setTimeout(poll, POLL_INTERVAL);
|
|
296
|
+
|
|
297
|
+
} catch (err) {
|
|
298
|
+
console.error("Polling error:", err);
|
|
299
|
+
// retry after interval (network glitch safe)
|
|
300
|
+
setTimeout(poll, POLL_INTERVAL);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
poll();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function openRazorpayCheckout(subscriptionId, razorpayKey) {
|
|
308
|
+
const options = {
|
|
309
|
+
key: razorpayKey, // razorpay public key
|
|
310
|
+
subscription_id: subscriptionId,
|
|
311
|
+
name: "Nano Banana AI",
|
|
312
|
+
description: "AI Image Generation Subscription",
|
|
313
|
+
handler: function (response) {
|
|
314
|
+
console.log("Payment Success:", response);
|
|
315
|
+
checkSubscriptionStatus(subscriptionId);
|
|
316
|
+
},
|
|
317
|
+
theme: {
|
|
318
|
+
color: "#6C5CE7"
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const rzp = new Razorpay(options);
|
|
323
|
+
rzp.open();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
async function buyPlan(planId, planName) {
|
|
328
|
+
try {
|
|
329
|
+
const overlay = createLoadingOverlay();
|
|
330
|
+
document.body.appendChild(overlay);
|
|
331
|
+
const authToken = await getAuthToken();
|
|
332
|
+
const res = await fetch(
|
|
333
|
+
`${PAYMENT_API_URL}/api/v1/payment-routes/create-subscription`,
|
|
334
|
+
{
|
|
335
|
+
method: "POST",
|
|
336
|
+
headers: {
|
|
337
|
+
"Content-Type": "application/json",
|
|
338
|
+
Authorization: `Bearer ${authToken}`,
|
|
339
|
+
},
|
|
340
|
+
body: JSON.stringify({
|
|
341
|
+
plan_id: planId,
|
|
342
|
+
"total_count": 1200,
|
|
343
|
+
"site_id": 2,
|
|
344
|
+
"customer_notify": true,
|
|
345
|
+
plan_name: planName
|
|
346
|
+
|
|
347
|
+
})
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
const data = await res.json();
|
|
352
|
+
console.log("Subscription Created:", data.id);
|
|
353
|
+
|
|
354
|
+
openRazorpayCheckout(data.id, "rzp_test_8eh9kvtfj5GEvR");
|
|
355
|
+
|
|
356
|
+
} catch (err) {
|
|
357
|
+
console.error("Create subscription error:", err);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
loadPricingPlans();
|
|
362
|
+
</script>
|
|
363
|
+
|
|
364
|
+
</body>
|
|
365
|
+
|
|
366
|
+
</html>
|