nodebb-plugin-niki-loyalty 1.5.0 → 1.5.5
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.
- package/library.js +69 -98
- package/niki-admin.txt +120 -143
- package/niki-kasa.txt +52 -22
- package/niki-prize.txt +200 -0
- package/niki-wallet.txt +415 -0
- package/package.json +1 -1
- package/static/lib/client.js +33 -26
- package/yeedek +313 -0
package/static/lib/client.js
CHANGED
|
@@ -82,7 +82,6 @@ $(document).ready(function () {
|
|
|
82
82
|
}, 300);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
console.log('[Niki-Loyalty] Toast gösterildi:', message);
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
// Fonksiyonu global yap (Konsoldan test için)
|
|
@@ -105,10 +104,8 @@ $(document).ready(function () {
|
|
|
105
104
|
if (data && typeof data.points !== 'undefined') {
|
|
106
105
|
var points = Math.floor(data.points);
|
|
107
106
|
$('#widget-user-points').text(points);
|
|
108
|
-
console.log('[Niki-Loyalty] Widget puanı güncellendi:', points);
|
|
109
107
|
}
|
|
110
108
|
}).fail(function () {
|
|
111
|
-
console.log('[Niki-Loyalty] Widget puanı yüklenemedi.');
|
|
112
109
|
});
|
|
113
110
|
}
|
|
114
111
|
// Fonksiyonu global yap
|
|
@@ -147,7 +144,6 @@ $(document).ready(function () {
|
|
|
147
144
|
if (response && response.success) {
|
|
148
145
|
// Puan kazanıldı! Bildirim göster
|
|
149
146
|
showNikiToast('Günlük giriş için <strong style="color:#ffd700">+' + response.earned + ' Puan</strong> kazandın! 👋');
|
|
150
|
-
console.log('[Niki-Loyalty] Günlük giriş puanı alındı. Yeni Toplam:', response.total);
|
|
151
147
|
|
|
152
148
|
// Widget'ı güncelle
|
|
153
149
|
if (typeof updateSidebarWidget === 'function') {
|
|
@@ -158,7 +154,6 @@ $(document).ready(function () {
|
|
|
158
154
|
localStorage.setItem(storageKey, today);
|
|
159
155
|
}).fail(function () {
|
|
160
156
|
// Hata durumunda sessizce devam et
|
|
161
|
-
console.log('[Niki-Loyalty] Günlük giriş kontrolü başarısız.');
|
|
162
157
|
});
|
|
163
158
|
}
|
|
164
159
|
|
|
@@ -177,13 +172,11 @@ $(document).ready(function () {
|
|
|
177
172
|
// ============================================================
|
|
178
173
|
// Sadece 'topic' (konu) sayfasındaysak sayaç çalışsın.
|
|
179
174
|
if (ajaxify.data && ajaxify.data.template && ajaxify.data.template.name === 'topic') {
|
|
180
|
-
console.log('[Niki-Loyalty] Konu sayfası algılandı, sayaç başlatılıyor...');
|
|
181
175
|
|
|
182
176
|
// 10 Dakikada bir tetikle (Günde 10 limit var backendde)
|
|
183
177
|
heartbeatInterval = setInterval(function () {
|
|
184
178
|
if (document.hidden) return; // Sekme aktif değilse sayma
|
|
185
179
|
|
|
186
|
-
console.log('[Niki-Loyalty] 10dk doldu. Puan isteniyor...');
|
|
187
180
|
|
|
188
181
|
$.post('/api/niki-loyalty/heartbeat', { _csrf: config.csrf_token }, function (response) {
|
|
189
182
|
if (response && response.earned) {
|
|
@@ -191,11 +184,9 @@ $(document).ready(function () {
|
|
|
191
184
|
if (typeof showNikiToast === 'function') {
|
|
192
185
|
showNikiToast('Konu okuduğun için <strong style="color:#ffd700">+1 Puan</strong> kazandın! 🐈');
|
|
193
186
|
}
|
|
194
|
-
console.log('[Niki-Loyalty] Heartbeat başarılı. Yeni Puan:', response.total);
|
|
195
187
|
// Widget'ı hemen güncelle
|
|
196
188
|
updateSidebarWidget();
|
|
197
189
|
} else {
|
|
198
|
-
console.log('[Niki-Loyalty] Puan gelmedi (Günlük okuma limiti dolmuş olabilir).');
|
|
199
190
|
}
|
|
200
191
|
});
|
|
201
192
|
}, 600000); // 10 Dakika = 600.000 ms
|
|
@@ -260,42 +251,59 @@ $(document).ready(function () {
|
|
|
260
251
|
let dailyScore = parseFloat(data.dailyScore);
|
|
261
252
|
let scoreText = Number.isInteger(dailyScore) ? dailyScore : dailyScore.toFixed(1);
|
|
262
253
|
$('#widget-daily-text').text(scoreText + ' / ' + data.dailyCap);
|
|
254
|
+
// Hedef label'ını da dinamik güncelle
|
|
255
|
+
$('.progress-text .target').text('Hedef: ' + data.dailyCap);
|
|
263
256
|
|
|
264
|
-
// 3.
|
|
265
|
-
const
|
|
257
|
+
// 3. ACTIONS bilgisiyle puan ve limitleri dinamik güncelle
|
|
258
|
+
const act = data.actions || {};
|
|
259
|
+
const c = data.counts || {};
|
|
266
260
|
|
|
267
261
|
// Helper: İlerleme Yazdırma Fonksiyonu
|
|
268
|
-
function setProgress(id, current, max, rowId) {
|
|
262
|
+
function setProgress(id, current, max, rowId, rewardText) {
|
|
269
263
|
current = parseInt(current || 0);
|
|
270
264
|
const el = $('#' + id);
|
|
271
265
|
const row = $('#' + rowId);
|
|
272
266
|
|
|
267
|
+
// Puan miktarını güncelle
|
|
268
|
+
if (rewardText) {
|
|
269
|
+
row.find('.item-reward').text(rewardText);
|
|
270
|
+
}
|
|
271
|
+
|
|
273
272
|
if (current >= max) {
|
|
274
273
|
el.html('<span style="color:#4caf50; font-weight:bold;">Tamamlandı ✅</span>');
|
|
275
|
-
row.addClass('completed');
|
|
274
|
+
row.addClass('completed');
|
|
276
275
|
} else {
|
|
277
|
-
el.text(
|
|
276
|
+
el.text(current + '/' + max + ' Tamamlandı');
|
|
278
277
|
row.removeClass('completed');
|
|
279
278
|
}
|
|
280
279
|
}
|
|
281
280
|
|
|
282
|
-
//
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
281
|
+
// Dinamik: backend ACTIONS'dan puan ve limit bilgilerini al
|
|
282
|
+
var loginAct = act.login || { points: 5, limit: 1 };
|
|
283
|
+
var topicAct = act.new_topic || { points: 5, limit: 1 };
|
|
284
|
+
var replyAct = act.reply || { points: 5, limit: 2 };
|
|
285
|
+
var readAct = act.read || { points: 1, limit: 10 };
|
|
286
|
+
var likeGivenAct = act.like_given || { points: 2.5, limit: 2 };
|
|
287
|
+
var likeTakenAct = act.like_taken || { points: 5, limit: 2 };
|
|
286
288
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// Not: Like limiti aslında alma 2 + atma 2 = 4.
|
|
291
|
-
// Kullanıcıya toplam 4 üzerinden göstermek kafa karıştırmaz.
|
|
292
|
-
setProgress('w-count-like', totalLike, 4, 'item-like');
|
|
289
|
+
setProgress('w-count-new_topic', c.new_topic, topicAct.limit, 'item-new-topic', '+' + topicAct.points);
|
|
290
|
+
setProgress('w-count-reply', c.reply, replyAct.limit, 'item-reply', '+' + replyAct.points);
|
|
291
|
+
setProgress('w-count-read', c.read, readAct.limit, 'item-read', '+' + readAct.points);
|
|
293
292
|
|
|
294
|
-
//
|
|
293
|
+
// Like: toplam limit = like_given.limit + like_taken.limit
|
|
294
|
+
var totalLikeLimit = likeGivenAct.limit + likeTakenAct.limit;
|
|
295
|
+
var totalLike = (parseInt(c.like_given || 0) + parseInt(c.like_taken || 0));
|
|
296
|
+
setProgress('w-count-like', totalLike, totalLikeLimit, 'item-like', '+' + likeGivenAct.points + '/+' + likeTakenAct.points);
|
|
297
|
+
|
|
298
|
+
// Login
|
|
295
299
|
if (c.login >= 1) {
|
|
296
300
|
$('#w-count-login').html('<span style="color:#4caf50;">Alındı ✅</span>');
|
|
297
301
|
$('#item-login').addClass('completed');
|
|
302
|
+
} else {
|
|
303
|
+
$('#w-count-login').text('Giriş Yapılmadı');
|
|
304
|
+
$('#item-login').removeClass('completed');
|
|
298
305
|
}
|
|
306
|
+
$('#item-login .item-reward').text('+' + loginAct.points);
|
|
299
307
|
});
|
|
300
308
|
}
|
|
301
309
|
|
|
@@ -372,7 +380,6 @@ $(document).ready(function () {
|
|
|
372
380
|
});
|
|
373
381
|
});
|
|
374
382
|
}).fail(function () {
|
|
375
|
-
console.log('[Niki-Loyalty] Cüzdan verileri yüklenemedi.');
|
|
376
383
|
});
|
|
377
384
|
}
|
|
378
385
|
|
package/yeedek
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
|
|
2
|
+
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js"></script>
|
|
3
|
+
|
|
4
|
+
<style>
|
|
5
|
+
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;700;800&display=swap');
|
|
6
|
+
|
|
7
|
+
.niki-wallet-wrapper{
|
|
8
|
+
max-width:380px;margin:40px auto;background:#FFF;
|
|
9
|
+
border-radius:30px;box-shadow:0 20px 60px rgba(0,0,0,0.08);
|
|
10
|
+
overflow:hidden;text-align:center;position:relative;
|
|
11
|
+
font-family:'Poppins',sans-serif;border:1px solid #F0F0F0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.niki-header-bg{background:#1a1a1a;height:140px;width:100%;position:absolute;top:0;left:0;border-radius:0 0 40px 40px;}
|
|
15
|
+
.niki-content{position:relative;z-index:1;padding:30px;padding-top:70px;}
|
|
16
|
+
|
|
17
|
+
.niki-avatar{width:110px;height:110px;border-radius:50%;background:#fff;margin:0 auto 15px;border:5px solid #fff;box-shadow:0 10px 30px rgba(0,0,0,0.1);display:flex;align-items:center;justify-content:center;position:relative;}
|
|
18
|
+
.niki-avatar img{width:100%;height:100%;object-fit:cover;border-radius:50%;}
|
|
19
|
+
|
|
20
|
+
.niki-balance-big{font-size:60px;font-weight:800;color:#1a1a1a;line-height:1;margin-bottom:5px;letter-spacing:-2px;}
|
|
21
|
+
.niki-label{color:#999;font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;margin-bottom:25px;}
|
|
22
|
+
|
|
23
|
+
.niki-bar-box{background:#FAFAFA;border-radius:20px;padding:25px 20px 40px;margin:25px 0;border:1px solid #EEE;position:relative;}
|
|
24
|
+
.niki-track{background:#E0E0E0;height:12px;border-radius:10px;width:100%;margin:15px 0;position:relative;}
|
|
25
|
+
.niki-fill{height:100%;background:#C5A065;width:0%;transition:width 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);border-radius:10px;box-shadow:0 0 10px rgba(197,160,101,0.4);}
|
|
26
|
+
|
|
27
|
+
.tier-dot{position:absolute;top:50%;transform:translate(-50%,-50%);width:12px;height:12px;background:#fff;border:3px solid #ccc;border-radius:50%;z-index:2;transition:all 0.3s;}
|
|
28
|
+
.tier-dot.reached{border-color:#C5A065;background:#C5A065;}
|
|
29
|
+
|
|
30
|
+
.tier-label{position:absolute;top:18px;transform:translateX(-50%);font-size:9px;color:#aaa;font-weight:600;width:60px;text-align:center;line-height:1.1;}
|
|
31
|
+
.tier-dot.reached + .tier-label{color:#C5A065;}
|
|
32
|
+
|
|
33
|
+
.niki-btn{
|
|
34
|
+
background:#1a1a1a;color:#fff;width:100%;padding:20px;
|
|
35
|
+
border-radius:18px;font-size:14px;font-weight:700;border:none;
|
|
36
|
+
cursor:pointer;display:flex;align-items:center;justify-content:center;gap:8px;
|
|
37
|
+
transition:transform 0.2s, box-shadow 0.2s;
|
|
38
|
+
}
|
|
39
|
+
.niki-btn:active{transform:scale(0.95);}
|
|
40
|
+
.niki-btn:disabled{background:#E0E0E0;color:#AAA;cursor:not-allowed;}
|
|
41
|
+
|
|
42
|
+
.qr-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(10,10,10,0.95);z-index:10000;display:none;align-items:center;justify-content:center;backdrop-filter:blur(10px);}
|
|
43
|
+
.ticket-card{background:#fff;width:320px;border-radius:30px;overflow:hidden;text-align:center;position:relative;animation:cardPop 0.4s cubic-bezier(0.175,0.885,0.32,1.275);box-shadow:0 0 0 8px rgba(255,255,255,0.1),0 30px 80px rgba(0,0,0,0.8);}
|
|
44
|
+
@keyframes cardPop{from{transform:scale(0.8) translateY(50px);opacity:0;}to{transform:scale(1) translateY(0);opacity:1;}}
|
|
45
|
+
|
|
46
|
+
.ticket-top{background:#1a1a1a;padding:25px;color:#C5A065;font-weight:700;letter-spacing:2px;font-size:14px;}
|
|
47
|
+
.ticket-body{padding:40px 30px;position:relative;}
|
|
48
|
+
#qrcode{display:flex;justify-content:center;margin-bottom:30px;}
|
|
49
|
+
#qrcode img{border:10px solid #fff;border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,0.1);}
|
|
50
|
+
.timer-wrapper{width:100%;height:6px;background:#eee;border-radius:10px;overflow:hidden;margin-top:10px;}
|
|
51
|
+
.timer-bar{height:100%;background:#C5A065;width:100%;transition:width 1s linear;}
|
|
52
|
+
.timer-text{font-size:12px;color:#888;margin-top:8px;font-weight:600;}
|
|
53
|
+
.close-circle{position:absolute;top:15px;right:15px;width:30px;height:30px;background:rgba(255,255,255,0.2);border-radius:50%;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;transition:background 0.2s;}
|
|
54
|
+
.close-circle:hover{background:rgba(255,255,255,0.4);}
|
|
55
|
+
|
|
56
|
+
.success-view{display:none;padding:40px 20px;}
|
|
57
|
+
.success-icon{width:100px;height:100px;background:#2E7D32;color:#fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:50px;margin:0 auto 20px;box-shadow:0 10px 30px rgba(46,125,50,0.3);animation:popCheck 0.5s ease;}
|
|
58
|
+
@keyframes popCheck{0%{transform:scale(0);}80%{transform:scale(1.1);}100%{transform:scale(1);}}
|
|
59
|
+
</style>
|
|
60
|
+
|
|
61
|
+
<div class="niki-wallet-wrapper" id="niki-wallet-root">
|
|
62
|
+
<div class="niki-header-bg"></div>
|
|
63
|
+
|
|
64
|
+
<div class="niki-content">
|
|
65
|
+
<div class="niki-avatar"><img src="" id="niki-logo-main"></div>
|
|
66
|
+
<div class="niki-balance-big" id="my-points">...</div>
|
|
67
|
+
<div class="niki-label">MEVCUT PUAN</div>
|
|
68
|
+
|
|
69
|
+
<div class="niki-bar-box">
|
|
70
|
+
<div style="display:flex; justify-content:space-between; font-size:12px; font-weight:700; color:#1a1a1a;">
|
|
71
|
+
<span>HEDEFLER</span><span id="target-txt">250</span>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="niki-track">
|
|
75
|
+
<div class="niki-fill" id="prog-bar"></div>
|
|
76
|
+
|
|
77
|
+
<div class="tier-dot" id="dot-1" style="left:24%;"></div>
|
|
78
|
+
<div class="tier-label" style="left:24%;">Kurabiye</div>
|
|
79
|
+
|
|
80
|
+
<div class="tier-dot" id="dot-2" style="left:48%;"></div>
|
|
81
|
+
<div class="tier-label" style="left:48%;">%30 İnd.</div>
|
|
82
|
+
|
|
83
|
+
<div class="tier-dot" id="dot-3" style="left:72%;"></div>
|
|
84
|
+
<div class="tier-label" style="left:72%;">%60 İnd.</div>
|
|
85
|
+
|
|
86
|
+
<div class="tier-dot" id="dot-4" style="left:100%;"></div>
|
|
87
|
+
<div class="tier-label" style="left:100%;">Kahve</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div style="font-size:10px; color:#aaa; margin-top:25px; text-align:center;">Ödüller Niki Kasasından alınır</div>
|
|
91
|
+
<div style="font-size:10px; color:#aaa; margin-top:25px; text-align:center;">Kurabiye Ödülü kahvenin yanında ücretsizdir</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<button id="btn-qr" class="niki-btn" onclick="openQR()" disabled>
|
|
95
|
+
<i class="fa fa-lock"></i> PUAN YETERSİZ
|
|
96
|
+
</button>
|
|
97
|
+
|
|
98
|
+
<div style="margin-top:25px; font-size:10px; color:#ccc;">
|
|
99
|
+
NIKI THE CAT COFFEE © LOYALTY
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<div id="modal-qr" class="qr-overlay">
|
|
105
|
+
<div class="ticket-card">
|
|
106
|
+
<div class="close-circle" onclick="closeQR()"><i class="fa fa-times"></i></div>
|
|
107
|
+
|
|
108
|
+
<div id="view-code">
|
|
109
|
+
<div class="ticket-top">KASAYA GÖSTERİNİZ</div>
|
|
110
|
+
<div class="ticket-body">
|
|
111
|
+
<div id="qrcode"></div>
|
|
112
|
+
<div style="font-size:14px; font-weight:700; color:#1a1a1a; margin-top:10px;">TARANIYOR...</div>
|
|
113
|
+
<div class="timer-wrapper"><div class="timer-bar" id="time-bar"></div></div>
|
|
114
|
+
<div class="timer-text" id="timer-txt">2:00</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div id="view-success" class="success-view">
|
|
119
|
+
<div class="success-icon"><i class="fa fa-check"></i></div>
|
|
120
|
+
<h2 style="font-size:24px; color:#1a1a1a; margin-bottom:10px;">AFİYET OLSUN!</h2>
|
|
121
|
+
<p style="color:#888; font-size:14px; margin-bottom:20px;">Ödeme alındı, ödülün verildi.</p>
|
|
122
|
+
<button class="niki-btn" onclick="closeQR()" style="padding:15px; font-size:14px;">TAMAM</button>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<script>
|
|
128
|
+
const MAX_GOAL = 250;
|
|
129
|
+
const TIERS = [
|
|
130
|
+
{ cost: 60, name: "Kurabiye" },
|
|
131
|
+
{ cost: 120, name: "%30 İndirim" },
|
|
132
|
+
{ cost: 180, name: "%60 İndirim" },
|
|
133
|
+
{ cost: 250, name: "Ücretsiz Kahve" }
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
let pollInterval = null;
|
|
137
|
+
let initialPoints = 0;
|
|
138
|
+
|
|
139
|
+
// ✅ tek seferde bir kere çalıştırmayı garanti etmek için
|
|
140
|
+
let walletBooted = false;
|
|
141
|
+
|
|
142
|
+
function resetDots() {
|
|
143
|
+
$('#dot-1,#dot-2,#dot-3,#dot-4').removeClass('reached');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function safeLoadData() {
|
|
147
|
+
// DOM hazır değilse kaç
|
|
148
|
+
if (!$('#niki-wallet-root').length) return;
|
|
149
|
+
|
|
150
|
+
const logoUrl = (config && config.relative_path ? config.relative_path : '') + "/plugins/nodebb-plugin-niki-loyalty/static/logo.png";
|
|
151
|
+
$("#niki-logo-main").attr("src", logoUrl);
|
|
152
|
+
|
|
153
|
+
$.get('/api/niki-loyalty/wallet-data')
|
|
154
|
+
.done(function(data) {
|
|
155
|
+
const p = parseInt(data && data.points, 10) || 0;
|
|
156
|
+
initialPoints = p;
|
|
157
|
+
|
|
158
|
+
$('#my-points').text(p);
|
|
159
|
+
|
|
160
|
+
resetDots();
|
|
161
|
+
|
|
162
|
+
let pct = (p / MAX_GOAL) * 100;
|
|
163
|
+
if (pct > 100) pct = 100;
|
|
164
|
+
$('#prog-bar').css('width', '0%');
|
|
165
|
+
setTimeout(() => { $('#prog-bar').css('width', pct + '%'); }, 60);
|
|
166
|
+
|
|
167
|
+
if (p >= 60) $('#dot-1').addClass('reached');
|
|
168
|
+
if (p >= 120) $('#dot-2').addClass('reached');
|
|
169
|
+
if (p >= 180) $('#dot-3').addClass('reached');
|
|
170
|
+
if (p >= 250) $('#dot-4').addClass('reached');
|
|
171
|
+
|
|
172
|
+
let bestReward = null;
|
|
173
|
+
for (let i = TIERS.length - 1; i >= 0; i--) {
|
|
174
|
+
if (p >= TIERS[i].cost) { bestReward = TIERS[i]; break; }
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const btn = $('#btn-qr');
|
|
178
|
+
if (bestReward) {
|
|
179
|
+
btn.prop('disabled', false)
|
|
180
|
+
.css('background', '#1a1a1a')
|
|
181
|
+
.html('<i class="fa fa-qrcode"></i> KULLAN: ' + String(bestReward.name).toUpperCase());
|
|
182
|
+
} else {
|
|
183
|
+
btn.prop('disabled', true)
|
|
184
|
+
.css('background', '#E0E0E0')
|
|
185
|
+
.html('<i class="fa fa-lock"></i> ' + (60 - p) + ' PUAN EKSİK');
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
.fail(function() {
|
|
189
|
+
// sayfa geçiş anında ajaxify sırasında bazen patlıyor -> tekrar dene
|
|
190
|
+
setTimeout(() => {
|
|
191
|
+
if ($('#niki-wallet-root').length) safeLoadData();
|
|
192
|
+
}, 250);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function bootWallet() {
|
|
197
|
+
if (walletBooted) return;
|
|
198
|
+
walletBooted = true;
|
|
199
|
+
|
|
200
|
+
// ilk yükleme
|
|
201
|
+
safeLoadData();
|
|
202
|
+
|
|
203
|
+
// ajaxify her sayfa bitişinde: bu sayfadaysak yeniden yükle
|
|
204
|
+
$(window).on('action:ajaxify.end.nikiWallet', function() {
|
|
205
|
+
if (window.location.pathname.indexOf('niki-wallet') > -1) {
|
|
206
|
+
safeLoadData();
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// bazı temalarda end gelmeyebiliyor -> content loaded'da da garanti
|
|
211
|
+
$(window).on('action:topic.loaded.nikiWallet action:widgets.loaded.nikiWallet action:ajaxify.contentLoaded.nikiWallet', function() {
|
|
212
|
+
if (window.location.pathname.indexOf('niki-wallet') > -1) {
|
|
213
|
+
safeLoadData();
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function openQR() {
|
|
219
|
+
if(!confirm("Mevcut puanınla alabileceğin EN YÜKSEK ödül kullanılacak. Onaylıyor musun?")) return;
|
|
220
|
+
|
|
221
|
+
$.post('/api/niki-loyalty/generate-qr', { _csrf: config.csrf_token }, function(res) {
|
|
222
|
+
if (res && res.success) {
|
|
223
|
+
$('#modal-qr').fadeIn(200).css('display', 'flex');
|
|
224
|
+
$('#view-code').show(); $('#view-success').hide();
|
|
225
|
+
$('#qrcode').empty();
|
|
226
|
+
|
|
227
|
+
new QRCode(document.getElementById("qrcode"), {
|
|
228
|
+
text: res.token,
|
|
229
|
+
width: 260, height: 260,
|
|
230
|
+
colorDark : "#000000", colorLight : "#ffffff",
|
|
231
|
+
correctLevel : QRCode.CorrectLevel.L
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
startTimer(120);
|
|
235
|
+
startPolling();
|
|
236
|
+
} else {
|
|
237
|
+
app.alertError(res && res.message ? res.message : 'Hata');
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function startPolling() {
|
|
243
|
+
clearInterval(pollInterval);
|
|
244
|
+
pollInterval = setInterval(() => {
|
|
245
|
+
// modal kapandıysa polling yapma
|
|
246
|
+
if (!$('#modal-qr').is(':visible')) { clearInterval(pollInterval); return; }
|
|
247
|
+
|
|
248
|
+
$.get('/api/niki-loyalty/wallet-data', function(data) {
|
|
249
|
+
const currentP = parseInt(data && data.points, 10) || 0;
|
|
250
|
+
if (currentP < initialPoints) {
|
|
251
|
+
clearInterval(pollInterval);
|
|
252
|
+
showSuccess();
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}, 2000);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function showSuccess() {
|
|
259
|
+
$('#view-code').hide();
|
|
260
|
+
$('#view-success').fadeIn(300);
|
|
261
|
+
confetti({ particleCount: 150, spread: 70, origin: { y: 0.6 }, colors: ['#C5A065', '#1a1a1a', '#ffffff'] });
|
|
262
|
+
try { new Audio('https://freesound.org/data/previews/171/171671_2437358-lq.mp3').play(); } catch(e){}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function startTimer(duration) {
|
|
266
|
+
let timer = duration;
|
|
267
|
+
$('#time-bar').css('width', '100%');
|
|
268
|
+
|
|
269
|
+
const countdown = setInterval(function() {
|
|
270
|
+
if (!$('#modal-qr').is(':visible') || $('#view-success').is(':visible')) {
|
|
271
|
+
clearInterval(countdown); return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const minutes = Math.floor(timer / 60);
|
|
275
|
+
const seconds = timer % 60;
|
|
276
|
+
$('#timer-txt').text(minutes + ":" + (seconds < 10 ? "0" + seconds : seconds));
|
|
277
|
+
|
|
278
|
+
const pct = (timer / duration) * 100;
|
|
279
|
+
$('#time-bar').css('width', pct + '%');
|
|
280
|
+
|
|
281
|
+
timer--;
|
|
282
|
+
if (timer < 0) {
|
|
283
|
+
clearInterval(countdown);
|
|
284
|
+
closeQR();
|
|
285
|
+
app.alertError("Süre doldu.");
|
|
286
|
+
}
|
|
287
|
+
}, 1000);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function closeQR() {
|
|
291
|
+
$('#modal-qr').fadeOut(200);
|
|
292
|
+
clearInterval(pollInterval);
|
|
293
|
+
pollInterval = null;
|
|
294
|
+
|
|
295
|
+
// modal kapandıktan sonra cüzdanı tekrar yükle
|
|
296
|
+
setTimeout(safeLoadData, 200);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ✅ NodeBB ajaxify: sayfa bu template'e geldiğinde boot edelim
|
|
300
|
+
$(window).on('action:ajaxify.end', function() {
|
|
301
|
+
if (window.location.pathname.indexOf('niki-wallet') > -1) {
|
|
302
|
+
walletBooted = false; // route tekrar gelince boot tekrar çalışsın
|
|
303
|
+
bootWallet();
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// ✅ ilk açılış (refresh / direkt url)
|
|
308
|
+
$(document).ready(function() {
|
|
309
|
+
if (window.location.pathname.indexOf('niki-wallet') > -1) {
|
|
310
|
+
bootWallet();
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
</script>
|