sequelize-game-bank 5.0.2 → 5.1.0

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/public/js/js.js CHANGED
@@ -180,6 +180,36 @@ async function loadData() {
180
180
  if (document.getElementById("table-logs")) {
181
181
  await loadTransactionLogs();
182
182
  }
183
+
184
+ const creditContainer = document.getElementById("active-credit-actions");
185
+ if (creditContainer) {
186
+ creditContainer.innerHTML = "";
187
+ let creditRes = await fetch("/api/bank/accounts/my-current-credit", {
188
+ headers: { "Bypass-Tunnel-Reminder": "true" },
189
+ });
190
+
191
+ if (creditRes.ok) {
192
+ let creditData = await creditRes.json();
193
+
194
+ if (creditData && creditData.activeCredit) {
195
+ const cr = creditData.activeCredit;
196
+ const regularPayment = cr.totalRepay / cr.termMonths;
197
+
198
+ creditContainer.innerHTML = `
199
+ <div class="credit-info-block" style="margin-top: 15px;">
200
+ <p>Остаток по кредиту: <b>${parseFloat(cr.remainingRepay).toFixed(2)}</b> руб.</p>
201
+ <button class="btn btn-success" onclick="payCreditManually(${parseInt(cr.id, 10)}, ${parseFloat(regularPayment)})">
202
+ Внести регулярный платеж (${regularPayment.toFixed(2)} руб.)
203
+ </button>
204
+ </div>
205
+ `;
206
+ } else {
207
+ creditContainer.innerHTML = `<p style="color: gray; margin-top: 15px;">У вас нет активных кредитов.</p>`;
208
+ }
209
+ }
210
+ }
211
+
212
+ await syncProfileSectionData();
183
213
  } catch (e) {
184
214
  console.error("Критическая ошибка выполнения скрипта страницы:", e);
185
215
  window.Swal.fire({
@@ -301,58 +331,6 @@ async function executeTransfer() {
301
331
  console.error("Ошибка [" + data.statusCode + "]: " + data.message);
302
332
  }
303
333
  }
304
- async function applyForCredit() {
305
- const targetAccountId = document.getElementById("credit-target").value;
306
- const amount = document.getElementById("credit-amount").value;
307
- const paymentsCount = document.getElementById("credit-payments").value;
308
- const autoWithdrawal = document.getElementById("credit-auto").checked;
309
- const pinCode = document.getElementById("credit-pin").value;
310
- const res = await fetch("/api/bank/accounts/credit", {
311
- method: "POST",
312
- headers: {
313
- "Content-Type": "application/json",
314
- "Bypass-Tunnel-Reminder": "true",
315
- },
316
- body: JSON.stringify({
317
- accountId: targetAccountId,
318
- amount: parseFloat(amount),
319
- termMonths: parseInt(paymentsCount, 10),
320
- autoRepay: autoWithdrawal,
321
- pinCode: pinCode,
322
- rate: 0.1,
323
- }),
324
- });
325
- const data = await res.json();
326
- if (data.success || data.status) {
327
- await Swal.fire({
328
- title: "Кредит",
329
- text:
330
- "Кредит одобрен! Деньги зачислены на счет #" +
331
- (data.creditId || data.creditAccountId),
332
- icon: "success",
333
- confirmButtonColor: "#3085d6",
334
- confirmButtonText: "Ок",
335
- });
336
-
337
- Toastify({
338
- text: `Вы взяли кредит`,
339
- duration: 3000,
340
- style: { background: "rgb(58, 245, 11)" },
341
- }).showToast();
342
-
343
- if (typeof loadData === "function") loadData();
344
- } else {
345
- await Swal.fire({
346
- title: "Кредит",
347
- text: data.error || data.message || "Ошибка оформления кредита",
348
- icon: "warning",
349
- iconColor: "orange",
350
- confirmButtonColor: "#3085d6",
351
- confirmButtonText: "Ок",
352
- });
353
- console.error("Ошибка: " + (data.error || data.message));
354
- }
355
- }
356
334
  document.getElementById("logoutBtn").addEventListener("click", async () => {
357
335
  const logOut = await Swal.fire({
358
336
  title: "Выход",
@@ -411,16 +389,22 @@ async function syncProfileSectionData() {
411
389
  const statusText = document.getElementById("2fa-current-status");
412
390
  const toggleBtn = document.getElementById("btn-toggle-2fa");
413
391
 
414
- if (user2FaActive) {
415
- statusText.innerHTML =
416
- 'Текущий статус: <span style="color:green; font-weight:bold;">ЗАЩИЩЕН (2FA включена)</span>';
417
- toggleBtn.innerText = "Отключить защиту 2FA";
418
- toggleBtn.className = "btn btn-danger";
392
+ if (statusText && toggleBtn) {
393
+ if (user2FaActive) {
394
+ statusText.innerHTML =
395
+ 'Текущий статус: <span style="color:green; font-weight:bold;">ЗАЩИЩЕН (2FA включена)</span>';
396
+ toggleBtn.innerText = "Отключить защиту 2FA";
397
+ toggleBtn.className = "btn btn-danger";
398
+ } else {
399
+ statusText.innerHTML =
400
+ 'Текущий статус: <span style="color:red; font-weight:bold;">НЕБЕЗОПАСНО (2FA выключена)</span>';
401
+ toggleBtn.innerText = "Включить защиту 2FA";
402
+ toggleBtn.className = "btn";
403
+ }
419
404
  } else {
420
- statusText.innerHTML =
421
- 'Текущий статус: <span style="color:red; font-weight:bold;">НЕБЕЗОПАСНО (2FA выключена)</span>';
422
- toggleBtn.innerText = "Включить защиту 2FA";
423
- toggleBtn.className = "btn";
405
+ console.log(
406
+ "ℹ️ Элементы управления 2FA не найдены на текущей вкладке (это нормально).",
407
+ );
424
408
  }
425
409
  }
426
410
  } catch (e) {
@@ -795,32 +779,56 @@ async function loadTransactionLogs() {
795
779
  }
796
780
  async function executeCreateCredit() {
797
781
  try {
798
- const accountIdField = document.getElementById("credit-accountId");
782
+ const accountIdField =
783
+ document.getElementById("credit-target") ||
784
+ document.getElementById("credit-accountId");
799
785
  const amountField = document.getElementById("credit-amount");
800
- const autoRepayField = document.getElementById("credit-autoRepay");
801
- const rateField = document.getElementById("credit-rate");
802
- const termMonthsField = document.getElementById("credit-termMonths");
803
- if (!accountIdField || !amountField) {
786
+ const termMonthsField =
787
+ document.getElementById("credit-payments") ||
788
+ document.getElementById("credit-termMonths");
789
+ const autoRepayField =
790
+ document.getElementById("credit-credit-auto") ||
791
+ document.getElementById("credit-auto") ||
792
+ document.getElementById("credit-autoRepay");
793
+ const pinCodeField = document.getElementById("credit-pin");
794
+
795
+ if (!accountIdField || !amountField || !pinCodeField) {
804
796
  console.error(
805
- "Критические элементы формы кредита не найдены в HTML дерева.",
797
+ "Критические элементы формы кредита (Счет, Сумма или Пин-код) не найдены в HTML.",
798
+ );
799
+ Swal.fire(
800
+ "Ошибка",
801
+ "Ошибка структуры формы. Обратитесь к администратору.",
802
+ "error",
806
803
  );
807
804
  return;
808
805
  }
809
- const accountId = accountIdField.value;
806
+
807
+ const targetAccountId = accountIdField.value;
810
808
  const amount = parseFloat(amountField.value);
809
+ const pinCode = pinCodeField.value.trim();
811
810
  const autoRepay = autoRepayField ? autoRepayField.checked : false;
812
- const rate = rateField ? parseFloat(rateField.value) : 0.1;
813
811
  const termMonths = termMonthsField
814
812
  ? parseInt(termMonthsField.value, 10)
815
813
  : 12;
816
- if (!accountId || isNaN(amount) || amount <= 0) {
814
+
815
+ if (!targetAccountId || isNaN(amount) || amount <= 0) {
816
+ Swal.fire(
817
+ "Внимание",
818
+ "Пожалуйста, выберите счет и укажите корректную сумму кредитования.",
819
+ "warning",
820
+ );
821
+ return;
822
+ }
823
+ if (!pinCode) {
817
824
  Swal.fire(
818
825
  "Внимание",
819
- "Пожалуйста, заполните номер счета и корректную сумму",
826
+ "Пожалуйста, введите PIN-код выбранного счета для подтверждения.",
820
827
  "warning",
821
828
  );
822
829
  return;
823
830
  }
831
+
824
832
  const response = await fetch("/api/bank/accounts/credit", {
825
833
  method: "POST",
826
834
  headers: {
@@ -828,37 +836,132 @@ async function executeCreateCredit() {
828
836
  "Bypass-Tunnel-Reminder": "true",
829
837
  },
830
838
  body: JSON.stringify({
831
- accountId,
832
- amount,
833
- autoRepay,
834
- rate,
835
- termMonths,
839
+ targetAccountId: targetAccountId,
840
+ amount: amount,
841
+ paymentsCount: termMonths,
842
+ autoWithdrawal: autoRepay,
843
+ pinCode: pinCode,
836
844
  }),
837
845
  });
846
+
838
847
  if (!response.ok) {
839
848
  throw new Error(`Ошибка сервера: ${response.status}`);
840
849
  }
850
+
841
851
  const result = await response.json();
842
- if (result.success) {
843
- Swal.fire(
844
- "Успех!",
845
- result.message || "Кредит успешно оформлен",
846
- "success",
847
- ).then(() => {
848
- location.href = "/bank/accounts.html";
852
+
853
+ if (result.success || result.status) {
854
+ await Swal.fire({
855
+ title: "Успех!",
856
+ text:
857
+ result.message ||
858
+ `Кредит одобрен! Деньги зачислены на счет #${targetAccountId}`,
859
+ icon: "success",
860
+ confirmButtonColor: "#3085d6",
861
+ confirmButtonText: "Ок",
849
862
  });
863
+
864
+ Toastify({
865
+ text: `Вы успешно взяли кредит`,
866
+ duration: 3000,
867
+ style: { background: "rgb(58, 245, 11)" },
868
+ }).showToast();
869
+
870
+ window.location.href = "/bank/accounts.html";
850
871
  } else {
851
- Swal.fire(
852
- "Ошибка оформления",
853
- result.error || "Не удалось выдать кредит",
854
- "error",
872
+ Swal.fire({
873
+ title: "Ошибка оформления",
874
+ text: result.error || result.message || "Не удалось выдать кредит",
875
+ icon: "warning",
876
+ iconColor: "orange",
877
+ confirmButtonColor: "#3085d6",
878
+ confirmButtonText: "Ок",
879
+ });
880
+ console.error(
881
+ "Ошибка оформления кредита: " + (result.error || result.message),
855
882
  );
856
883
  }
857
884
  } catch (error) {
858
885
  console.error("Ошибка выполнения executeCreateCredit:", error);
859
886
  Swal.fire(
860
887
  "Критическая ошибка",
861
- "Не удалось связаться с сервером банка",
888
+ "Не удалось связаться с сервером банка или обработать запрос",
889
+ "error",
890
+ );
891
+ }
892
+ }
893
+ async function payCreditManually(creditId, defaultAmount) {
894
+ const { value: formValues } = await Swal.fire({
895
+ title: "Погашение кредита",
896
+ html:
897
+ `<div style="text-align: left; margin-bottom: 8px;"><label style="font-weight:bold;">Сумма платежа (руб.)</label></div>` +
898
+ `<input id="swal-pay-amount" class="swal2-input" type="number" value="${parseFloat(defaultAmount).toFixed(2)}" min="1" step="any">` +
899
+ `<div style="text-align: left; margin-top: 12px; margin-bottom: 8px;"><label style="font-weight:bold;">PIN-код вашего счета</label></div>` +
900
+ `<input id="swal-pay-pin" class="swal2-input" type="password" placeholder="••••" maxlength="4">`,
901
+ focusConfirm: false,
902
+ showCancelButton: true,
903
+ confirmButtonText: "Оплатить",
904
+ cancelButtonText: "Отмена",
905
+ preConfirm: () => {
906
+ const amountVal = document.getElementById("swal-pay-amount").value;
907
+ const pinVal = document.getElementById("swal-pay-pin").value;
908
+ return {
909
+ amount: amountVal,
910
+ pinCode: pinVal,
911
+ };
912
+ },
913
+ });
914
+
915
+ if (!formValues || !formValues.amount || !formValues.pinCode) return;
916
+
917
+ try {
918
+ const res = await fetch("/api/bank/accounts/credit/pay", {
919
+ method: "POST",
920
+ headers: {
921
+ "Content-Type": "application/json",
922
+ "Bypass-Tunnel-Reminder": "true",
923
+ },
924
+ body: JSON.stringify({
925
+ creditId: parseInt(creditId, 10),
926
+ amount: parseFloat(formValues.amount),
927
+ pinCode: formValues.pinCode.trim(),
928
+ }),
929
+ });
930
+
931
+ const contentType = res.headers.get("content-type");
932
+ if (!contentType || !contentType.includes("application/json")) {
933
+ const textError = await res.text();
934
+ console.error("Критический ответ бэка:", textError);
935
+ Swal.fire(
936
+ "Ошибка сервера",
937
+ "Сервер вернул некорректный текстовый ответ. Проверьте консоль Node.js.",
938
+ "error",
939
+ );
940
+ return;
941
+ }
942
+
943
+ const data = await res.json();
944
+
945
+ if (data.status) {
946
+ await Swal.fire({
947
+ title: "Успех!",
948
+ text: data.message,
949
+ icon: "success",
950
+ });
951
+
952
+ if (typeof loadData === "function") loadData();
953
+ } else {
954
+ Swal.fire(
955
+ "Ошибка оплаты",
956
+ data.message || "Не удалось провести транзакцию",
957
+ "warning",
958
+ );
959
+ }
960
+ } catch (err) {
961
+ console.error("Ошибка запроса:", err);
962
+ Swal.fire(
963
+ "Критическая ошибка",
964
+ "Не удалось связаться с сервером банка.",
862
965
  "error",
863
966
  );
864
967
  }