@ozdao/martyrs 0.2.591 → 0.2.592

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.
Files changed (37) hide show
  1. package/dist/auth.server.js +7 -0
  2. package/dist/martyrs/src/components/EditImages/{EditImages.vue2.js → EditImages.vue.js} +2 -2
  3. package/dist/martyrs/src/components/EditImages/EditImages.vue.js.map +1 -0
  4. package/dist/martyrs/src/modules/auth/locales/en.js +2 -1
  5. package/dist/martyrs/src/modules/auth/locales/en.js.map +1 -1
  6. package/dist/martyrs/src/modules/auth/locales/ru.js +2 -1
  7. package/dist/martyrs/src/modules/auth/locales/ru.js.map +1 -1
  8. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +7 -11
  9. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js.map +1 -1
  10. package/dist/martyrs/src/modules/auth/views/store/auth.js +10 -2
  11. package/dist/martyrs/src/modules/auth/views/store/auth.js.map +1 -1
  12. package/dist/martyrs/src/modules/core/core.client.js +3 -3
  13. package/dist/martyrs/src/modules/core/core.client.js.map +1 -1
  14. package/dist/martyrs/src/modules/core/views/components/elements/OnlineIndicator.vue.js +1 -1
  15. package/dist/martyrs/src/modules/core/views/components/elements/OnlineIndicator.vue.js.map +1 -1
  16. package/dist/martyrs/src/modules/core/views/components/icons/IconMenu.vue.js +44 -0
  17. package/dist/martyrs/src/modules/core/views/components/icons/IconMenu.vue.js.map +1 -0
  18. package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js +44 -50
  19. package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js.map +1 -1
  20. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
  21. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
  22. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +1 -1
  23. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +1 -1
  24. package/dist/style.css +17 -53
  25. package/package.json +5 -2
  26. package/src/modules/TASKS.MD +30 -1
  27. package/src/modules/auth/controllers/routes/auth.routes.js +9 -0
  28. package/src/modules/auth/locales/en.js +2 -1
  29. package/src/modules/auth/locales/ru.js +2 -1
  30. package/src/modules/auth/views/components/pages/SignUp.vue +2 -5
  31. package/src/modules/auth/views/store/auth.js +13 -3
  32. package/src/modules/core/core.client.js +2 -2
  33. package/src/modules/core/views/components/elements/OnlineIndicator.vue +1 -1
  34. package/src/modules/core/views/components/icons/IconMenu.vue +82 -0
  35. package/src/modules/core/views/components/partials/Header.vue +167 -305
  36. package/dist/martyrs/src/components/EditImages/EditImages.vue2.js.map +0 -1
  37. package/src/modules/PROCESS.md +0 -0
@@ -278,6 +278,13 @@ const authRoutes = (function(app, db, origins) {
278
278
  controller.signup
279
279
  );
280
280
  app.post("/api/auth/signin", controller.signin);
281
+ app.get("/api/auth/check-token", [authJwt.verifyToken()], (req, res) => {
282
+ res.status(200).json({
283
+ ok: true,
284
+ userId: req.userId,
285
+ sessionId: req.sessionId || null
286
+ });
287
+ });
281
288
  app.post(
282
289
  "/api/auth/reset-password",
283
290
  [
@@ -2,7 +2,7 @@ import { ref, watchEffect, createElementBlock, openBlock, createBlock, createCom
2
2
  import { VueDraggableNext } from "../../../../node_modules/.pnpm/vue-draggable-next@2.2.1_sortablejs@1.15.6_vue@3.5.13_typescript@5.8.3_/node_modules/vue-draggable-next/dist/vue-draggable-next.esm-bundler.js";
3
3
  import _sfc_main$2 from "../UploadImageMultiple/UploadImageMultiple.vue.js";
4
4
  import _sfc_main$1 from "../../modules/icons/navigation/IconCross.vue.js";
5
- /* empty css */
5
+ /* empty css */
6
6
  const _hoisted_1 = { class: "flex-nowrap flex gap-small" };
7
7
  const _hoisted_2 = { class: "pos-relative" };
8
8
  const _hoisted_3 = ["src"];
@@ -92,4 +92,4 @@ const _sfc_main = {
92
92
  export {
93
93
  _sfc_main as default
94
94
  };
95
- //# sourceMappingURL=EditImages.vue2.js.map
95
+ //# sourceMappingURL=EditImages.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EditImages.vue.js","sources":["../../../../../src/components/EditImages/EditImages.vue"],"sourcesContent":["<template>\n\t<div class=\"flex-nowrap flex gap-small\">\n <VueDraggableNext v-if=\"localImages.length > 0\" class=\"gap-small flex dragArea list-group w-full\" v-model=\"localImages\" @change=\"emitChanges\">\n\t\t\t<div v-for=\"(image, index) in localImages\" class=\"pos-relative\">\n\t\t\t\t<img loading=\"lazy\" class=\"i-extra object-fit-contain bg-black-transp-5 pd-nano radius-small o-hidden\" :src=\"(FILE_SERVER_URL || '') + image\" />\n\t\t\t\t\n <IconCross \n @click=\"deleteImage(index)\" \n class=\"cursor-pointer pos-absolute t-center flex-center flex radius-extra i-medium bg-red pos-t-10-negative pos-r-10-negative pd-micro\"\n />\n\t\t\t</div>\n\t\t</VueDraggableNext>\n <div\n v-if=\"localImages.length > 0\" \n class=\"i-extra uppercase flex-center flex radius-small o-hidden br-main br-2px pd-small\"\n >\n <UploadImageMultiple \n @update:images=\"onImagesUpdate\"\n text=\"Add\"\n :options=\"{\n showText: false\n }\"\n :uploadPath=\"'photos'\"\n class=\"radius-big\"\n />\n </div>\n\n\n\t\t<UploadImageMultiple \t\n v-if=\"localImages.length < 1\" \n @update:images=\"onImagesUpdate\"\n :uploadPath=\"props.uploadPath\"\n :text=\"props.text\"\n :options=\"props.options\"\n class=\"w-100 pd-medium\"\n />\n\t</div>\t\n</template>\n\n<script setup>\nimport { ref, defineProps, watchEffect } from 'vue';\nimport { VueDraggableNext } from 'vue-draggable-next'\nimport UploadImageMultiple from \"@martyrs/src/components/UploadImageMultiple/UploadImageMultiple.vue\";\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\n\nconst props = defineProps({\n images: Array,\n text: Object,\n options: Object,\n uploadPath: {\n type: Object,\n default: 'unsorted'\n }\n});\n\nconst emit = defineEmits(['update:images'])\n\nconst localImages = ref([...props.images])\n\nwatchEffect(() => {\n localImages.value = [...props.images]; // Обновление localImages при изменении props.images\n});\n\nconst emitChanges = () => {\n emit('update:images', localImages.value)\n}\n\nconst onImagesUpdate = (newImages) => {\n localImages.value = [...localImages.value, ...newImages]\n emitChanges()\n}\n\nconst deleteImage = (index) => {\n localImages.value.splice(index, 1)\n emitChanges()\n}\n</script>\n\n<style lang=\"scss\">\n// Your styles here\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,UAAM,QAAQ;AAUd,UAAM,OAAO;AAEb,UAAM,cAAc,IAAI,CAAC,GAAG,MAAM,MAAM,CAAC;AAEzC,gBAAY,MAAM;AAChB,kBAAY,QAAQ,CAAC,GAAG,MAAM,MAAM;AAAA,IACtC,CAAC;AAED,UAAM,cAAc,MAAM;AACxB,WAAK,iBAAiB,YAAY,KAAK;AAAA,IACzC;AAEA,UAAM,iBAAiB,CAAC,cAAc;AACpC,kBAAY,QAAQ,CAAC,GAAG,YAAY,OAAO,GAAG,SAAS;AACvD,kBAAW;AAAA,IACb;AAEA,UAAM,cAAc,CAAC,UAAU;AAC7B,kBAAY,MAAM,OAAO,OAAO,CAAC;AACjC,kBAAW;AAAA,IACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -32,7 +32,8 @@ const en = {
32
32
  emailNotice: "We will send you an email with a confirmation code that you will need to enter in the next step.",
33
33
  smsNotice: "We will send you an SMS with a confirmation code that you will need to enter in the next step.",
34
34
  sendCode: "Send Code",
35
- haveAccount: "Already have an account?"
35
+ haveAccount: "Already have an account?",
36
+ agreement: "By registering, you agree to our <a href='/legal/eula' target='_blank'>End User License Agreement (EULA)</a>"
36
37
  },
37
38
  enterCode: {
38
39
  verifyNumberTitle: "Verify Number",
@@ -1 +1 @@
1
- {"version":3,"file":"en.js","sources":["../../../../../../src/modules/auth/locales/en.js"],"sourcesContent":["// @martyrs/src/modules/auth/locales/en.js\nexport default {\n auth: {\n popup: {\n title: \"Welcome\",\n subtitle: \"Please sign in or create an account to continue.\",\n signUp: \"Sign Up\",\n haveAccount: \"Already have an account?\",\n signIn: \"Sign in\"\n },\n signIn: {\n title: \"Welcome to OZ DAO,\",\n subtitle: \"Sign In to Continue\",\n signup: \"Don't have an account?\",\n phone: \"Phone\",\n email: \"Email\",\n phonePlaceholder: \"Enter your phone\",\n emailPlaceholder: \"Enter your email\",\n haveAccount: \"Don't have an account? Sign Up\",\n passwordPlaceholder: \"Enter your password\",\n forgotPassword: \"Forgot Password?\",\n signin: \"Sign In\",\n signin_apple: \"Sign In with Apple\",\n soon: \"SOON\"\n },\n signUp: {\n title: \"Sign Up\",\n description: \"Choose a convenient way to register via phone or email:\",\n phone: \"Phone\",\n email: \"Email\",\n phonePlaceholder: \"Enter your phone\",\n emailPlaceholder: \"Enter your email\",\n emailNotice: \"We will send you an email with a confirmation code that you will need to enter in the next step.\",\n smsNotice: \"We will send you an SMS with a confirmation code that you will need to enter in the next step.\",\n sendCode: \"Send Code\",\n haveAccount: \"Already have an account?\"\n },\n enterCode: {\n verifyNumberTitle: \"Verify Number\",\n instructions: \"We have sent a registration code to your phone number. Please enter it in the field below:\",\n resendCode: \"Send the code again\",\n secondsResend: \"seconds to the possibility of sending the code again.\"\n },\n resetPassword: {\n forgotPasswordTitle: \"Forgot Password?\",\n instructions: \"To reset your password, specify the phone or email used during registration.\",\n smsInfo: \"We will send you an SMS with a confirmation code to reset your password, which you will need to enter in the next step.\",\n emailInfo: \"We will send you an email with a confirmation code to reset your password, which you will need to enter in the next step.\",\n phone: \"Phone\",\n email: \"Email\",\n phonePlaceholder: \"Enter your phone\",\n emailPlaceholder: \"Enter your email\",\n sendCode: \"Send code\"\n },\n enterPassword: {\n almostDone: \"Almost there!\",\n newPasswordPrompt: \"Please, set a new password.\",\n registrationPasswordPrompt: \"Please, set your password to complete the registration.\",\n passwordPlaceholder: \"Password\",\n repeatPasswordPlaceholder: \"Repeat Password\",\n changePasswordBtn: \"Change Password\",\n registerBtn: \"Register\"\n },\n features: [\n {\n title: \"What's the Weeder Token, Dude?\",\n description: \"WDT is like, the backbone of our rad community. It's cash, it's power, it's an investment. Groovy, right?\"\n },\n {\n title: \"Light Up and Level Up\",\n description: \"Order up, light up, and earn Weeder tokens. More tokes, more cash in your pocket, man.\"\n },\n {\n title: \"Hang Ten with Our Community\",\n description: \"Find the dopest strains and start floating on cloud 9 with us!\"\n },\n {\n title: \"Shop 'Til You Drop... Into Your Couch\",\n description: \"Score primo bud and gear with just a few clicks. Delivered right to your pad!\"\n }\n ]\n }\n};"],"names":[],"mappings":"AACA,MAAA,KAAe;AAAA,EACb,MAAM;AAAA,IACJ,OAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,QAAQ;AAAA,IACd;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,MAAM;AAAA,IACZ;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa;AAAA,IACnB;AAAA,IACI,WAAW;AAAA,MACT,mBAAmB;AAAA,MACnB,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,eAAe;AAAA,IACrB;AAAA,IACI,eAAe;AAAA,MACb,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,UAAU;AAAA,IAChB;AAAA,IACI,eAAe;AAAA,MACb,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,4BAA4B;AAAA,MAC5B,qBAAqB;AAAA,MACrB,2BAA2B;AAAA,MAC3B,mBAAmB;AAAA,MACnB,aAAa;AAAA,IACnB;AAAA,IACI,UAAU;AAAA,MACR;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,IACA;AAAA,EACA;AACA;"}
1
+ {"version":3,"file":"en.js","sources":["../../../../../../src/modules/auth/locales/en.js"],"sourcesContent":["// @martyrs/src/modules/auth/locales/en.js\nexport default {\n auth: {\n popup: {\n title: \"Welcome\",\n subtitle: \"Please sign in or create an account to continue.\",\n signUp: \"Sign Up\",\n haveAccount: \"Already have an account?\",\n signIn: \"Sign in\"\n },\n signIn: {\n title: \"Welcome to OZ DAO,\",\n subtitle: \"Sign In to Continue\",\n signup: \"Don't have an account?\",\n phone: \"Phone\",\n email: \"Email\",\n phonePlaceholder: \"Enter your phone\",\n emailPlaceholder: \"Enter your email\",\n haveAccount: \"Don't have an account? Sign Up\",\n passwordPlaceholder: \"Enter your password\",\n forgotPassword: \"Forgot Password?\",\n signin: \"Sign In\",\n signin_apple: \"Sign In with Apple\",\n soon: \"SOON\"\n },\n signUp: {\n title: \"Sign Up\",\n description: \"Choose a convenient way to register via phone or email:\",\n phone: \"Phone\",\n email: \"Email\",\n phonePlaceholder: \"Enter your phone\",\n emailPlaceholder: \"Enter your email\",\n emailNotice: \"We will send you an email with a confirmation code that you will need to enter in the next step.\",\n smsNotice: \"We will send you an SMS with a confirmation code that you will need to enter in the next step.\",\n sendCode: \"Send Code\",\n haveAccount: \"Already have an account?\",\n agreement: \"By registering, you agree to our <a href='/legal/eula' target='_blank'>End User License Agreement (EULA)</a>\"\n },\n enterCode: {\n verifyNumberTitle: \"Verify Number\",\n instructions: \"We have sent a registration code to your phone number. Please enter it in the field below:\",\n resendCode: \"Send the code again\",\n secondsResend: \"seconds to the possibility of sending the code again.\"\n },\n resetPassword: {\n forgotPasswordTitle: \"Forgot Password?\",\n instructions: \"To reset your password, specify the phone or email used during registration.\",\n smsInfo: \"We will send you an SMS with a confirmation code to reset your password, which you will need to enter in the next step.\",\n emailInfo: \"We will send you an email with a confirmation code to reset your password, which you will need to enter in the next step.\",\n phone: \"Phone\",\n email: \"Email\",\n phonePlaceholder: \"Enter your phone\",\n emailPlaceholder: \"Enter your email\",\n sendCode: \"Send code\"\n },\n enterPassword: {\n almostDone: \"Almost there!\",\n newPasswordPrompt: \"Please, set a new password.\",\n registrationPasswordPrompt: \"Please, set your password to complete the registration.\",\n passwordPlaceholder: \"Password\",\n repeatPasswordPlaceholder: \"Repeat Password\",\n changePasswordBtn: \"Change Password\",\n registerBtn: \"Register\"\n },\n features: [\n {\n title: \"What's the Weeder Token, Dude?\",\n description: \"WDT is like, the backbone of our rad community. It's cash, it's power, it's an investment. Groovy, right?\"\n },\n {\n title: \"Light Up and Level Up\",\n description: \"Order up, light up, and earn Weeder tokens. More tokes, more cash in your pocket, man.\"\n },\n {\n title: \"Hang Ten with Our Community\",\n description: \"Find the dopest strains and start floating on cloud 9 with us!\"\n },\n {\n title: \"Shop 'Til You Drop... Into Your Couch\",\n description: \"Score primo bud and gear with just a few clicks. Delivered right to your pad!\"\n }\n ]\n }\n};"],"names":[],"mappings":"AACA,MAAA,KAAe;AAAA,EACb,MAAM;AAAA,IACJ,OAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,QAAQ;AAAA,IACd;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,MAAM;AAAA,IACZ;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa;AAAA,MACb,WAAW;AAAA,IACjB;AAAA,IACI,WAAW;AAAA,MACT,mBAAmB;AAAA,MACnB,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,eAAe;AAAA,IACrB;AAAA,IACI,eAAe;AAAA,MACb,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,UAAU;AAAA,IAChB;AAAA,IACI,eAAe;AAAA,MACb,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,4BAA4B;AAAA,MAC5B,qBAAqB;AAAA,MACrB,2BAA2B;AAAA,MAC3B,mBAAmB;AAAA,MACnB,aAAa;AAAA,IACnB;AAAA,IACI,UAAU;AAAA,MACR;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,IACA;AAAA,EACA;AACA;"}
@@ -32,7 +32,8 @@ const ru = {
32
32
  emailNotice: "Мы отправим вам электронное письмо с кодом подтверждения, который вы должны будете ввести в следующем шаге.",
33
33
  smsNotice: "Мы вышлем вам SMS с кодом подтверждения, который вы должны будете ввести в следующем шаге.",
34
34
  sendCode: "Отправить код",
35
- haveAccount: "У вас уже есть аккаунт?"
35
+ haveAccount: "У вас уже есть аккаунт?",
36
+ agreement: "Регистрируясь, вы соглашаетесь с <a href='/legal/eula' target='_blank'>Пользовательским соглашением (EULA)</a>"
36
37
  },
37
38
  enterCode: {
38
39
  verifyNumberTitle: "Подтвердите номер",
@@ -1 +1 @@
1
- {"version":3,"file":"ru.js","sources":["../../../../../../src/modules/auth/locales/ru.js"],"sourcesContent":["// @martyrs/src/modules/auth/locales/ru.js\nexport default {\n auth: {\n popup: {\n title: \"Добро пожаловать\",\n subtitle: \"Войдите или создайте аккаунт для продолжения.\",\n signUp: \"Регистрация\",\n haveAccount: \"Уже есть аккаунт?\",\n signIn: \"Войти\"\n },\n signIn: {\n title: \"Приветствуем вас,\",\n subtitle: \"Войдите для продолжения\",\n signup: \"Нет аккаунта?\",\n phone: \"Телефон\",\n email: \"Email\",\n phonePlaceholder: \"Введите ваш телефон\",\n emailPlaceholder: \"Введите ваш email\",\n haveAccount: \"Нет аккаунта? Зарегистрироваться\",\n passwordPlaceholder: \"Введите ваш пароль\",\n forgotPassword: \"Забыли пароль?\",\n signin: \"Войти\",\n signin_apple: \"Войти через Apple\",\n soon: \"СКОРО\"\n },\n signUp: {\n title: \"Новая учетная запись\",\n description: \"Выберите удобный способ регистрации через телефон или email:\",\n phone: \"Телефон\",\n email: \"Email\",\n phonePlaceholder: \"Введите ваш телефон\",\n emailPlaceholder: \"Введите ваш email\",\n emailNotice: \"Мы отправим вам электронное письмо с кодом подтверждения, который вы должны будете ввести в следующем шаге.\",\n smsNotice: \"Мы вышлем вам SMS с кодом подтверждения, который вы должны будете ввести в следующем шаге.\",\n sendCode: \"Отправить код\",\n haveAccount: \"У вас уже есть аккаунт?\"\n },\n enterCode: {\n verifyNumberTitle: \"Подтвердите номер\",\n verifyEmailTitle: \"Подтвердите email\",\n instructions: \"Мы отправили код регистрации на ваш номер телефона. Введите его в поле ниже:\",\n instructionsEmail: \"Мы отправили код регистрации на ваш email. Введите его в поле ниже:\",\n resendCode: \"Отправить код еще раз\",\n secondsResend: \"секунд до возможности отправить код еще раз.\"\n },\n resetPassword: {\n forgotPasswordTitle: \"Забыли пароль?\",\n instructions: \"Чтобы сбросить пароль, укажите телефон или email, использованные при регистрации.\",\n smsInfo: \"Мы вышлем вам SMS с кодом подтверждения для сброса пароля, который вы должны будете ввести в следующем шаге.\",\n emailInfo: \"Мы отправим вам электронное письмо с кодом подтверждения для сброса пароля, который вы должны будете ввести в следующем шаге.\",\n phone: \"Телефон\",\n email: \"Email\",\n phonePlaceholder: \"Введите ваш телефон\",\n emailPlaceholder: \"Введите ваш email\",\n sendCode: \"Отправить код\"\n },\n enterPassword: {\n almostDone: \"Почти все!\",\n newPasswordPrompt: \"Пожалуйста, укажите новый пароль.\",\n registrationPasswordPrompt: \"Пожалуйста, укажите пароль, на этом регистрация будет закончена.\",\n passwordPlaceholder: \"Пароль\",\n repeatPasswordPlaceholder: \"Повторите пароль\",\n changePasswordBtn: \"Поменять пароль\",\n registerBtn: \"Зарегистрироваться\"\n },\n features: [\n {\n title: \"Что такое токен Weeder, Бро?\",\n description: \"WDT - это как основа нашего крутого сообщества. Это деньги, это власть, это инвестиции. Круто, а?\"\n },\n {\n title: \"Зажигай и Развивайся\",\n description: \"Закажи шмали, курни и зарабатывай токены Weeder. Чем больше курнешь, тем больше кэша у тебя в кармане, чувак.\"\n },\n {\n title: \"Веселись с Нашим Сообществом\",\n description: \"Найди самые крутые сорта и начни шмалить на девятом облаке вместе с нами.\"\n },\n {\n title: \"Покупайте, Когда Накурились\",\n description: \"Закажи премиумную бошку и крутые аксессуары за пару кликов, чувак. Прямо к твоей двери!\"\n }\n ]\n }\n};"],"names":[],"mappings":"AACA,MAAA,KAAe;AAAA,EACb,MAAM;AAAA,IACJ,OAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,QAAQ;AAAA,IACd;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,MAAM;AAAA,IACZ;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa;AAAA,IACnB;AAAA,IACI,WAAW;AAAA,MACT,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,YAAY;AAAA,MACZ,eAAe;AAAA,IACrB;AAAA,IACI,eAAe;AAAA,MACb,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,UAAU;AAAA,IAChB;AAAA,IACI,eAAe;AAAA,MACb,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,4BAA4B;AAAA,MAC5B,qBAAqB;AAAA,MACrB,2BAA2B;AAAA,MAC3B,mBAAmB;AAAA,MACnB,aAAa;AAAA,IACnB;AAAA,IACI,UAAU;AAAA,MACR;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,IACA;AAAA,EACA;AACA;"}
1
+ {"version":3,"file":"ru.js","sources":["../../../../../../src/modules/auth/locales/ru.js"],"sourcesContent":["// @martyrs/src/modules/auth/locales/ru.js\nexport default {\n auth: {\n popup: {\n title: \"Добро пожаловать\",\n subtitle: \"Войдите или создайте аккаунт для продолжения.\",\n signUp: \"Регистрация\",\n haveAccount: \"Уже есть аккаунт?\",\n signIn: \"Войти\"\n },\n signIn: {\n title: \"Приветствуем вас,\",\n subtitle: \"Войдите для продолжения\",\n signup: \"Нет аккаунта?\",\n phone: \"Телефон\",\n email: \"Email\",\n phonePlaceholder: \"Введите ваш телефон\",\n emailPlaceholder: \"Введите ваш email\",\n haveAccount: \"Нет аккаунта? Зарегистрироваться\",\n passwordPlaceholder: \"Введите ваш пароль\",\n forgotPassword: \"Забыли пароль?\",\n signin: \"Войти\",\n signin_apple: \"Войти через Apple\",\n soon: \"СКОРО\"\n },\n signUp: {\n title: \"Новая учетная запись\",\n description: \"Выберите удобный способ регистрации через телефон или email:\",\n phone: \"Телефон\",\n email: \"Email\",\n phonePlaceholder: \"Введите ваш телефон\",\n emailPlaceholder: \"Введите ваш email\",\n emailNotice: \"Мы отправим вам электронное письмо с кодом подтверждения, который вы должны будете ввести в следующем шаге.\",\n smsNotice: \"Мы вышлем вам SMS с кодом подтверждения, который вы должны будете ввести в следующем шаге.\",\n sendCode: \"Отправить код\",\n haveAccount: \"У вас уже есть аккаунт?\",\n agreement: \"Регистрируясь, вы соглашаетесь с <a href='/legal/eula' target='_blank'>Пользовательским соглашением (EULA)</a>\"\n },\n enterCode: {\n verifyNumberTitle: \"Подтвердите номер\",\n verifyEmailTitle: \"Подтвердите email\",\n instructions: \"Мы отправили код регистрации на ваш номер телефона. Введите его в поле ниже:\",\n instructionsEmail: \"Мы отправили код регистрации на ваш email. Введите его в поле ниже:\",\n resendCode: \"Отправить код еще раз\",\n secondsResend: \"секунд до возможности отправить код еще раз.\"\n },\n resetPassword: {\n forgotPasswordTitle: \"Забыли пароль?\",\n instructions: \"Чтобы сбросить пароль, укажите телефон или email, использованные при регистрации.\",\n smsInfo: \"Мы вышлем вам SMS с кодом подтверждения для сброса пароля, который вы должны будете ввести в следующем шаге.\",\n emailInfo: \"Мы отправим вам электронное письмо с кодом подтверждения для сброса пароля, который вы должны будете ввести в следующем шаге.\",\n phone: \"Телефон\",\n email: \"Email\",\n phonePlaceholder: \"Введите ваш телефон\",\n emailPlaceholder: \"Введите ваш email\",\n sendCode: \"Отправить код\"\n },\n enterPassword: {\n almostDone: \"Почти все!\",\n newPasswordPrompt: \"Пожалуйста, укажите новый пароль.\",\n registrationPasswordPrompt: \"Пожалуйста, укажите пароль, на этом регистрация будет закончена.\",\n passwordPlaceholder: \"Пароль\",\n repeatPasswordPlaceholder: \"Повторите пароль\",\n changePasswordBtn: \"Поменять пароль\",\n registerBtn: \"Зарегистрироваться\"\n },\n features: [\n {\n title: \"Что такое токен Weeder, Бро?\",\n description: \"WDT - это как основа нашего крутого сообщества. Это деньги, это власть, это инвестиции. Круто, а?\"\n },\n {\n title: \"Зажигай и Развивайся\",\n description: \"Закажи шмали, курни и зарабатывай токены Weeder. Чем больше курнешь, тем больше кэша у тебя в кармане, чувак.\"\n },\n {\n title: \"Веселись с Нашим Сообществом\",\n description: \"Найди самые крутые сорта и начни шмалить на девятом облаке вместе с нами.\"\n },\n {\n title: \"Покупайте, Когда Накурились\",\n description: \"Закажи премиумную бошку и крутые аксессуары за пару кликов, чувак. Прямо к твоей двери!\"\n }\n ]\n }\n};"],"names":[],"mappings":"AACA,MAAA,KAAe;AAAA,EACb,MAAM;AAAA,IACJ,OAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,QAAQ;AAAA,IACd;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,MAAM;AAAA,IACZ;AAAA,IACI,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa;AAAA,MACb,WAAW;AAAA,IACjB;AAAA,IACI,WAAW;AAAA,MACT,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,YAAY;AAAA,MACZ,eAAe;AAAA,IACrB;AAAA,IACI,eAAe;AAAA,MACb,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,UAAU;AAAA,IAChB;AAAA,IACI,eAAe;AAAA,MACb,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,4BAA4B;AAAA,MAC5B,qBAAqB;AAAA,MACrB,2BAA2B;AAAA,MAC3B,mBAAmB;AAAA,MACnB,aAAa;AAAA,IACnB;AAAA,IACI,UAAU;AAAA,MACR;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,MACM;AAAA,QACE,OAAO;AAAA,QACP,aAAa;AAAA,MACrB;AAAA,IACA;AAAA,EACA;AACA;"}
@@ -22,7 +22,8 @@ const _hoisted_6 = { class: "mn-b-small t-transp" };
22
22
  const _hoisted_7 = { class: "mn-b-semi radius-small o-hidden" };
23
23
  const _hoisted_8 = { class: "mn-b-small t-transp" };
24
24
  const _hoisted_9 = { class: "mn-b-semi" };
25
- const _hoisted_10 = { class: "w-100" };
25
+ const _hoisted_10 = ["innerHTML"];
26
+ const _hoisted_11 = { class: "w-100" };
26
27
  const _sfc_main = {
27
28
  __name: "SignUp",
28
29
  setup(__props) {
@@ -171,15 +172,10 @@ const _sfc_main = {
171
172
  class: "bg-light pd-small radius-small"
172
173
  }, null, 8, ["field", "placeholder"])
173
174
  ]),
174
- _cache[5] || (_cache[5] = createElementVNode("div", { class: "p-regular fw-semi mn-b-semi" }, [
175
- createTextVNode(" By registering, you agree to our "),
176
- createElementVNode("a", {
177
- class: "t-grey",
178
- href: "/legal/eula",
179
- target: "_blank",
180
- rel: "noopener noreferrer"
181
- }, "End User License Agreement (EULA)")
182
- ], -1)),
175
+ createElementVNode("div", {
176
+ class: "p-regular fw-semi mn-b-semi",
177
+ innerHTML: unref(t)("auth.signUp.agreement")
178
+ }, null, 8, _hoisted_10),
183
179
  createVNode(_sfc_main$3, {
184
180
  submit: onSubmit,
185
181
  class: "w-100 bg-main mn-b-big"
@@ -189,7 +185,7 @@ const _sfc_main = {
189
185
  ]),
190
186
  _: 1
191
187
  }),
192
- createElementVNode("div", _hoisted_10, [
188
+ createElementVNode("div", _hoisted_11, [
193
189
  createVNode(_component_router_link, {
194
190
  to: { name: "Sign In", query: { returnUrl: unref(route).query.returnUrl } },
195
191
  class: "underline mn-b-medium d-block t-blue"
@@ -1 +1 @@
1
- {"version":3,"file":"SignUp.vue.js","sources":["../../../../../../../../src/modules/auth/views/components/pages/SignUp.vue"],"sourcesContent":["<template>\n <section class=\"t-left pd-medium\">\n <h3 class=\"mn-b-small\">{{ t('auth.signUp.title') }}</h3>\n\n <!-- Tab selector -->\n <div\n v-if=\"availableTabs.length > 1\"\n class=\"mn-b-small p-small uppercase fw-semi bg-light radius-small o-hidden\"\n >\n <Tab\n v-model:selected=\"tabAuth\"\n :tabs=\"availableTabs\"\n classTab=\"pd-small pd-r-medium pd-l-medium w-100 pd-small radius-small\"\n />\n </div>\n\n <!-- Form -->\n <div class=\"pos-relative\">\n <!-- Phone -->\n <transition name=\"slide-fade\">\n <div v-show=\"tabAuth === 'phone'\" class=\"mn-b-semi radius-small\">\n <p class=\"mn-b-small t-transp\">{{ t('auth.signUp.smsNotice') }}</p>\n <FieldPhone\n @change=\"(event) => phone = event\"\n :dropdownOptions=\"{\n showDialCodeInSelection: true,\n showFlags: true,\n showDialCodeInList: true\n }\"\n :validation=\"phoneValidation\"\n mode=\"national\"\n :inputOptions=\"{ placeholder: t('auth.signUp.phonePlaceholder') }\"\n class=\"bg-light h-4r pd-small radius-small mn-b-thin\"\n />\n </div>\n </transition>\n <!-- Email -->\n <transition name=\"slide-fade\">\n <div v-show=\"tabAuth === 'email'\" class=\"mn-b-semi radius-small o-hidden\">\n <p class=\"mn-b-small t-transp\">{{ t('auth.signUp.emailNotice') }}</p>\n <Field\n v-model:field=\"email\"\n :placeholder=\"t('auth.signUp.emailPlaceholder')\"\n :validation=\"emailValidation\"\n class=\"bg-light h-4r pd-medium radius-small\"\n />\n </div>\n </transition>\n </div>\n\n <!-- Password fields -->\n <div class=\"mn-b-semi\">\n <Field\n v-model:field=\"password\"\n type=\"password\"\n :placeholder=\"t('auth.enterPassword.passwordPlaceholder')\"\n :validation=\"passwordValidation\"\n class=\"bg-light pd-small radius-small mn-b-thin\"\n />\n <Field\n v-model:field=\"passwordRepeat\"\n type=\"password\"\n :placeholder=\"t('auth.enterPassword.repeatPasswordPlaceholder')\"\n class=\"bg-light pd-small radius-small\"\n />\n </div>\n\n <!-- EULA -->\n <div class=\"p-regular fw-semi mn-b-semi\">\n By registering, you agree to our\n <a class=\"t-grey\" href=\"/legal/eula\" target=\"_blank\" rel=\"noopener noreferrer\">End User License Agreement (EULA)</a>\n </div>\n\n <!-- Button -->\n <Button :submit=\"onSubmit\" class=\"w-100 bg-main mn-b-big\">\n {{ t('auth.enterPassword.registerBtn') }}\n </Button>\n\n <!-- Links -->\n <div class=\"w-100\">\n <router-link\n :to=\"{ name: 'Sign In', query: { returnUrl: route.query.returnUrl } }\"\n class=\"underline mn-b-medium d-block t-blue\"\n >\n {{ t('auth.signUp.haveAccount') }}\n </router-link>\n </div>\n </section>\n</template>\n\n<script setup>\nimport Tab from '@martyrs/src/components/Tab/Tab.vue'\nimport Field from '@martyrs/src/components/Field/Field.vue'\nimport FieldPhone from '@martyrs/src/components/FieldPhone/FieldPhone.vue'\nimport Button from '@martyrs/src/components/Button/Button.vue'\n\nimport { computed, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\n\nimport { useStore } from '@martyrs/src/modules/core/views/store/core.store.js'\nimport { setError } from '@martyrs/src/modules/core/views/store/core.store.js'\nimport { withOtp } from '@martyrs/src/modules/auth/views/plugins/otp.plugin.js'\nimport $axios from '@martyrs/src/modules/core/views/utils/axios-instance.js'\nimport * as inputsValidation from '@martyrs/src/modules/auth/views/validations/inputs.validation'\n\nconst store = useStore()\nconst core = store.core || { state: {} }\nconst auth = store.auth\n\nconst route = useRoute()\nconst router = useRouter()\nconst { t } = useI18n({ useScope: 'global' })\n\nconst email = ref('')\nconst phone = ref('')\nconst password = ref('')\nconst passwordRepeat = ref('')\n\nconst phoneValidation = ref(null)\nconst emailValidation = ref(null)\nconst passwordValidation = ref(null)\n\nconst availableTabs = computed(() => {\n const tabs = [\n { name: t('auth.signUp.phone'), value: 'phone' },\n { name: t('auth.signUp.email'), value: 'email' }\n ]\n const excludeMethods = core.state?.options?.auth?.authMethodsExclude || []\n return tabs.filter(tab => !excludeMethods.includes(tab.value))\n})\n\nconst tabAuth = ref(availableTabs.value.length ? availableTabs.value[0].value : '')\n\nasync function onSubmit() {\n // Validate identifier\n if (tabAuth.value === 'phone') {\n await inputsValidation.validateInputs(\n phoneValidation,\n inputsValidation.validatePhone,\n phone.value,\n 'Некорректный телефон'\n )\n }\n if (tabAuth.value === 'email') {\n await inputsValidation.validateInputs(\n emailValidation,\n inputsValidation.validateEmail,\n email.value,\n 'Некорректный email'\n )\n }\n\n // Validate password\n await inputsValidation.validateInputs(\n passwordValidation,\n inputsValidation.validatePassword,\n password.value,\n 'Некорректный пароль'\n )\n\n if (password.value !== passwordRepeat.value) {\n setError({ response: { data: { errorCode: 'PASSWORDS_DO_NOT_MATCH' } } })\n throw new Error('PASSWORDS_DO_NOT_MATCH')\n }\n\n // Signup with OTP verification\n try {\n const result = await withOtp(\n (data) => $axios.post('/api/auth/signup', data),\n {\n email: tabAuth.value === 'email' ? email.value : undefined,\n phone: tabAuth.value === 'phone' ? phone.value : undefined,\n password: password.value,\n type: tabAuth.value,\n inviteCode: route.query.invite\n }\n )\n\n // Success - save token and redirect\n if (result.data?.accessToken) {\n const Cookies = (await import('js-cookie')).default\n Cookies.set('user', JSON.stringify(result.data), { path: '/', expires: 7 })\n await auth.actions.initialize()\n\n if (route.query.returnUrl) {\n router.push({ path: route.query.returnUrl, query: { afterAuth: 'true' } })\n } else {\n router.push({ name: 'User Profile', params: { _id: result.data._id }, query: { afterAuth: 'true' } })\n }\n }\n } catch (error) {\n setError(error)\n throw error\n }\n}\n</script>\n\n<style lang=\"scss\">\n.slide-fade-enter-active,\n.slide-fade-leave-active {\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.slide-fade-enter-from,\n.slide-fade-leave-to {\n position: absolute;\n transform: translateX(20px);\n opacity: 0;\n left: 0;\n top: 0;\n}\n</style>\n"],"names":["inputsValidation.validateInputs","inputsValidation.validatePhone","inputsValidation.validateEmail","inputsValidation.validatePassword"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0GA,UAAM,QAAQ,SAAQ;AACtB,UAAM,OAAO,MAAM,QAAQ,EAAE,OAAO,CAAA,EAAE;AACtC,UAAM,OAAO,MAAM;AAEnB,UAAM,QAAQ,SAAQ;AACtB,UAAM,SAAS,UAAS;AACxB,UAAM,EAAE,EAAC,IAAK,QAAQ,EAAE,UAAU,SAAQ,CAAE;AAE5C,UAAM,QAAQ,IAAI,EAAE;AACpB,UAAM,QAAQ,IAAI,EAAE;AACpB,UAAM,WAAW,IAAI,EAAE;AACvB,UAAM,iBAAiB,IAAI,EAAE;AAE7B,UAAM,kBAAkB,IAAI,IAAI;AAChC,UAAM,kBAAkB,IAAI,IAAI;AAChC,UAAM,qBAAqB,IAAI,IAAI;AAEnC,UAAM,gBAAgB,SAAS,MAAM;AACnC,YAAM,OAAO;AAAA,QACX,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,QAAO;AAAA,QAC9C,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,QAAO;AAAA,MAClD;AACE,YAAM,iBAAiB,KAAK,OAAO,SAAS,MAAM,sBAAsB,CAAA;AACxE,aAAO,KAAK,OAAO,SAAO,CAAC,eAAe,SAAS,IAAI,KAAK,CAAC;AAAA,IAC/D,CAAC;AAED,UAAM,UAAU,IAAI,cAAc,MAAM,SAAS,cAAc,MAAM,CAAC,EAAE,QAAQ,EAAE;AAElF,mBAAe,WAAW;AAExB,UAAI,QAAQ,UAAU,SAAS;AAC7B,cAAMA;AAAAA,UACJ;AAAA,UACAC;AAAAA,UACA,MAAM;AAAA,UACN;AAAA,QACN;AAAA,MACE;AACA,UAAI,QAAQ,UAAU,SAAS;AAC7B,cAAMD;AAAAA,UACJ;AAAA,UACAE;AAAAA,UACA,MAAM;AAAA,UACN;AAAA,QACN;AAAA,MACE;AAGA,YAAMF;AAAAA,QACJ;AAAA,QACAG;AAAAA,QACA,SAAS;AAAA,QACT;AAAA,MACJ;AAEE,UAAI,SAAS,UAAU,eAAe,OAAO;AAC3C,iBAAS,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,yBAAwB,IAAI,CAAE;AACxE,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAGA,UAAI;AACF,cAAM,SAAS,MAAM;AAAA,UACnB,CAAC,SAAS,OAAO,KAAK,oBAAoB,IAAI;AAAA,UAC9C;AAAA,YACE,OAAO,QAAQ,UAAU,UAAU,MAAM,QAAQ;AAAA,YACjD,OAAO,QAAQ,UAAU,UAAU,MAAM,QAAQ;AAAA,YACjD,UAAU,SAAS;AAAA,YACnB,MAAM,QAAQ;AAAA,YACd,YAAY,MAAM,MAAM;AAAA,UAChC;AAAA,QACA;AAGI,YAAI,OAAO,MAAM,aAAa;AAC5B,gBAAM,WAAW,MAAM,OAAO,kGAAW,GAAG;AAC5C,kBAAQ,IAAI,QAAQ,KAAK,UAAU,OAAO,IAAI,GAAG,EAAE,MAAM,KAAK,SAAS,EAAC,CAAE;AAC1E,gBAAM,KAAK,QAAQ,WAAU;AAE7B,cAAI,MAAM,MAAM,WAAW;AACzB,mBAAO,KAAK,EAAE,MAAM,MAAM,MAAM,WAAW,OAAO,EAAE,WAAW,SAAQ,CAAE;AAAA,UAC3E,OAAO;AACL,mBAAO,KAAK,EAAE,MAAM,gBAAgB,QAAQ,EAAE,KAAK,OAAO,KAAK,IAAG,GAAI,OAAO,EAAE,WAAW,OAAM,EAAE,CAAE;AAAA,UACtG;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,iBAAS,KAAK;AACd,cAAM;AAAA,MACR;AAAA,IACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"SignUp.vue.js","sources":["../../../../../../../../src/modules/auth/views/components/pages/SignUp.vue"],"sourcesContent":["<template>\n <section class=\"t-left pd-medium\">\n <h3 class=\"mn-b-small\">{{ t('auth.signUp.title') }}</h3>\n\n <!-- Tab selector -->\n <div\n v-if=\"availableTabs.length > 1\"\n class=\"mn-b-small p-small uppercase fw-semi bg-light radius-small o-hidden\"\n >\n <Tab\n v-model:selected=\"tabAuth\"\n :tabs=\"availableTabs\"\n classTab=\"pd-small pd-r-medium pd-l-medium w-100 pd-small radius-small\"\n />\n </div>\n\n <!-- Form -->\n <div class=\"pos-relative\">\n <!-- Phone -->\n <transition name=\"slide-fade\">\n <div v-show=\"tabAuth === 'phone'\" class=\"mn-b-semi radius-small\">\n <p class=\"mn-b-small t-transp\">{{ t('auth.signUp.smsNotice') }}</p>\n <FieldPhone\n @change=\"(event) => phone = event\"\n :dropdownOptions=\"{\n showDialCodeInSelection: true,\n showFlags: true,\n showDialCodeInList: true\n }\"\n :validation=\"phoneValidation\"\n mode=\"national\"\n :inputOptions=\"{ placeholder: t('auth.signUp.phonePlaceholder') }\"\n class=\"bg-light h-4r pd-small radius-small mn-b-thin\"\n />\n </div>\n </transition>\n <!-- Email -->\n <transition name=\"slide-fade\">\n <div v-show=\"tabAuth === 'email'\" class=\"mn-b-semi radius-small o-hidden\">\n <p class=\"mn-b-small t-transp\">{{ t('auth.signUp.emailNotice') }}</p>\n <Field\n v-model:field=\"email\"\n :placeholder=\"t('auth.signUp.emailPlaceholder')\"\n :validation=\"emailValidation\"\n class=\"bg-light h-4r pd-medium radius-small\"\n />\n </div>\n </transition>\n </div>\n\n <!-- Password fields -->\n <div class=\"mn-b-semi\">\n <Field\n v-model:field=\"password\"\n type=\"password\"\n :placeholder=\"t('auth.enterPassword.passwordPlaceholder')\"\n :validation=\"passwordValidation\"\n class=\"bg-light pd-small radius-small mn-b-thin\"\n />\n <Field\n v-model:field=\"passwordRepeat\"\n type=\"password\"\n :placeholder=\"t('auth.enterPassword.repeatPasswordPlaceholder')\"\n class=\"bg-light pd-small radius-small\"\n />\n </div>\n\n <!-- Agreement -->\n <div class=\"p-regular fw-semi mn-b-semi\" v-html=\"t('auth.signUp.agreement')\"></div>\n\n <!-- Button -->\n <Button :submit=\"onSubmit\" class=\"w-100 bg-main mn-b-big\">\n {{ t('auth.enterPassword.registerBtn') }}\n </Button>\n\n <!-- Links -->\n <div class=\"w-100\">\n <router-link\n :to=\"{ name: 'Sign In', query: { returnUrl: route.query.returnUrl } }\"\n class=\"underline mn-b-medium d-block t-blue\"\n >\n {{ t('auth.signUp.haveAccount') }}\n </router-link>\n </div>\n </section>\n</template>\n\n<script setup>\nimport Tab from '@martyrs/src/components/Tab/Tab.vue'\nimport Field from '@martyrs/src/components/Field/Field.vue'\nimport FieldPhone from '@martyrs/src/components/FieldPhone/FieldPhone.vue'\nimport Button from '@martyrs/src/components/Button/Button.vue'\n\nimport { computed, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\n\nimport { useStore } from '@martyrs/src/modules/core/views/store/core.store.js'\nimport { setError } from '@martyrs/src/modules/core/views/store/core.store.js'\nimport { withOtp } from '@martyrs/src/modules/auth/views/plugins/otp.plugin.js'\nimport $axios from '@martyrs/src/modules/core/views/utils/axios-instance.js'\nimport * as inputsValidation from '@martyrs/src/modules/auth/views/validations/inputs.validation'\n\nconst store = useStore()\nconst core = store.core || { state: {} }\nconst auth = store.auth\n\nconst route = useRoute()\nconst router = useRouter()\nconst { t } = useI18n({ useScope: 'global' })\n\nconst email = ref('')\nconst phone = ref('')\nconst password = ref('')\nconst passwordRepeat = ref('')\n\nconst phoneValidation = ref(null)\nconst emailValidation = ref(null)\nconst passwordValidation = ref(null)\n\nconst availableTabs = computed(() => {\n const tabs = [\n { name: t('auth.signUp.phone'), value: 'phone' },\n { name: t('auth.signUp.email'), value: 'email' }\n ]\n const excludeMethods = core.state?.options?.auth?.authMethodsExclude || []\n return tabs.filter(tab => !excludeMethods.includes(tab.value))\n})\n\nconst tabAuth = ref(availableTabs.value.length ? availableTabs.value[0].value : '')\n\nasync function onSubmit() {\n // Validate identifier\n if (tabAuth.value === 'phone') {\n await inputsValidation.validateInputs(\n phoneValidation,\n inputsValidation.validatePhone,\n phone.value,\n 'Некорректный телефон'\n )\n }\n if (tabAuth.value === 'email') {\n await inputsValidation.validateInputs(\n emailValidation,\n inputsValidation.validateEmail,\n email.value,\n 'Некорректный email'\n )\n }\n\n // Validate password\n await inputsValidation.validateInputs(\n passwordValidation,\n inputsValidation.validatePassword,\n password.value,\n 'Некорректный пароль'\n )\n\n if (password.value !== passwordRepeat.value) {\n setError({ response: { data: { errorCode: 'PASSWORDS_DO_NOT_MATCH' } } })\n throw new Error('PASSWORDS_DO_NOT_MATCH')\n }\n\n // Signup with OTP verification\n try {\n const result = await withOtp(\n (data) => $axios.post('/api/auth/signup', data),\n {\n email: tabAuth.value === 'email' ? email.value : undefined,\n phone: tabAuth.value === 'phone' ? phone.value : undefined,\n password: password.value,\n type: tabAuth.value,\n inviteCode: route.query.invite\n }\n )\n\n // Success - save token and redirect\n if (result.data?.accessToken) {\n const Cookies = (await import('js-cookie')).default\n Cookies.set('user', JSON.stringify(result.data), { path: '/', expires: 7 })\n await auth.actions.initialize()\n\n if (route.query.returnUrl) {\n router.push({ path: route.query.returnUrl, query: { afterAuth: 'true' } })\n } else {\n router.push({ name: 'User Profile', params: { _id: result.data._id }, query: { afterAuth: 'true' } })\n }\n }\n } catch (error) {\n setError(error)\n throw error\n }\n}\n</script>\n\n<style lang=\"scss\">\n.slide-fade-enter-active,\n.slide-fade-leave-active {\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.slide-fade-enter-from,\n.slide-fade-leave-to {\n position: absolute;\n transform: translateX(20px);\n opacity: 0;\n left: 0;\n top: 0;\n}\n</style>\n"],"names":["inputsValidation.validateInputs","inputsValidation.validatePhone","inputsValidation.validateEmail","inputsValidation.validatePassword"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuGA,UAAM,QAAQ,SAAQ;AACtB,UAAM,OAAO,MAAM,QAAQ,EAAE,OAAO,CAAA,EAAE;AACtC,UAAM,OAAO,MAAM;AAEnB,UAAM,QAAQ,SAAQ;AACtB,UAAM,SAAS,UAAS;AACxB,UAAM,EAAE,EAAC,IAAK,QAAQ,EAAE,UAAU,SAAQ,CAAE;AAE5C,UAAM,QAAQ,IAAI,EAAE;AACpB,UAAM,QAAQ,IAAI,EAAE;AACpB,UAAM,WAAW,IAAI,EAAE;AACvB,UAAM,iBAAiB,IAAI,EAAE;AAE7B,UAAM,kBAAkB,IAAI,IAAI;AAChC,UAAM,kBAAkB,IAAI,IAAI;AAChC,UAAM,qBAAqB,IAAI,IAAI;AAEnC,UAAM,gBAAgB,SAAS,MAAM;AACnC,YAAM,OAAO;AAAA,QACX,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,QAAO;AAAA,QAC9C,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,QAAO;AAAA,MAClD;AACE,YAAM,iBAAiB,KAAK,OAAO,SAAS,MAAM,sBAAsB,CAAA;AACxE,aAAO,KAAK,OAAO,SAAO,CAAC,eAAe,SAAS,IAAI,KAAK,CAAC;AAAA,IAC/D,CAAC;AAED,UAAM,UAAU,IAAI,cAAc,MAAM,SAAS,cAAc,MAAM,CAAC,EAAE,QAAQ,EAAE;AAElF,mBAAe,WAAW;AAExB,UAAI,QAAQ,UAAU,SAAS;AAC7B,cAAMA;AAAAA,UACJ;AAAA,UACAC;AAAAA,UACA,MAAM;AAAA,UACN;AAAA,QACN;AAAA,MACE;AACA,UAAI,QAAQ,UAAU,SAAS;AAC7B,cAAMD;AAAAA,UACJ;AAAA,UACAE;AAAAA,UACA,MAAM;AAAA,UACN;AAAA,QACN;AAAA,MACE;AAGA,YAAMF;AAAAA,QACJ;AAAA,QACAG;AAAAA,QACA,SAAS;AAAA,QACT;AAAA,MACJ;AAEE,UAAI,SAAS,UAAU,eAAe,OAAO;AAC3C,iBAAS,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,yBAAwB,IAAI,CAAE;AACxE,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAGA,UAAI;AACF,cAAM,SAAS,MAAM;AAAA,UACnB,CAAC,SAAS,OAAO,KAAK,oBAAoB,IAAI;AAAA,UAC9C;AAAA,YACE,OAAO,QAAQ,UAAU,UAAU,MAAM,QAAQ;AAAA,YACjD,OAAO,QAAQ,UAAU,UAAU,MAAM,QAAQ;AAAA,YACjD,UAAU,SAAS;AAAA,YACnB,MAAM,QAAQ;AAAA,YACd,YAAY,MAAM,MAAM;AAAA,UAChC;AAAA,QACA;AAGI,YAAI,OAAO,MAAM,aAAa;AAC5B,gBAAM,WAAW,MAAM,OAAO,kGAAW,GAAG;AAC5C,kBAAQ,IAAI,QAAQ,KAAK,UAAU,OAAO,IAAI,GAAG,EAAE,MAAM,KAAK,SAAS,EAAC,CAAE;AAC1E,gBAAM,KAAK,QAAQ,WAAU;AAE7B,cAAI,MAAM,MAAM,WAAW;AACzB,mBAAO,KAAK,EAAE,MAAM,MAAM,MAAM,WAAW,OAAO,EAAE,WAAW,SAAQ,CAAE;AAAA,UAC3E,OAAO;AACL,mBAAO,KAAK,EAAE,MAAM,gBAAgB,QAAQ,EAAE,KAAK,OAAO,KAAK,IAAG,GAAI,OAAO,EAAE,WAAW,OAAM,EAAE,CAAE;AAAA,UACtG;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,iBAAS,KAAK;AACd,cAAM;AAAA,MACR;AAAA,IACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -29,8 +29,16 @@ const actions = {
29
29
  if (userCookie) {
30
30
  const { _id, email, phone, avatar, roles, accessToken } = userCookie;
31
31
  setAuthToken(accessToken);
32
- const response = await $axios.get("/api/organizations/check-accesses");
33
- const userAccesses = response.data;
32
+ await $axios.get("/api/auth/check-token");
33
+ let userAccesses = [];
34
+ try {
35
+ const response = await $axios.get("/api/organizations/check-accesses");
36
+ userAccesses = response.data;
37
+ } catch (error) {
38
+ if (error.response?.status !== 404) {
39
+ throw error;
40
+ }
41
+ }
34
42
  state.accesses = userAccesses;
35
43
  Object.assign(state.user, { _id, email, phone, avatar });
36
44
  Object.assign(state.access, { token: accessToken, roles, status: !!accessToken });
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sources":["../../../../../../../src/modules/auth/views/store/auth.js"],"sourcesContent":["// Dependencies\nimport $axios, { setAuthToken } from '@martyrs/src/modules/core/views/utils/axios-instance.js';\nimport Cookies from 'js-cookie';\n// Capacitor\nimport { Preferences } from '@capacitor/preferences';\n// Vue modules\nimport { reactive, watch } from 'vue';\n// Globals\nimport { useSession, setError } from '@martyrs/src/modules/core/views/store/core.store.js';\nimport wsManager from '@martyrs/src/modules/core/views/classes/ws.manager.js';\n\n// State\nconst state = reactive({\n user: {\n _id: undefined,\n avatar: null,\n username: '',\n email: '',\n phone: '',\n password: '',\n passwordRepeat: '',\n },\n access: {\n roles: null,\n token: null,\n status: false,\n },\n accesses: [],\n});\n\n// Session manager\nconst session = useSession();\n\nconst actions = {\n async initialize(cookie) {\n try {\n const userCookie = cookie ? cookie : await getCookie('user');\n\n if (userCookie) {\n const { _id, email, phone, avatar, roles, accessToken } = userCookie;\n\n setAuthToken(accessToken);\n\n // Проверка токена через серверный маршрут\n const response = await $axios.get('/api/organizations/check-accesses');\n const userAccesses = response.data;\n\n // ТОЛЬКО ПОСЛЕ УСПЕШНОЙ ПРОВЕРКИ устанавливаем состояние\n state.accesses = userAccesses;\n Object.assign(state.user, { _id, email, phone, avatar });\n Object.assign(state.access, { token: accessToken, roles, status: !!accessToken });\n\n // Update Session with full user data\n session.set({ ...userCookie, accesses: userAccesses });\n\n // Переподключаем WebSocket если пользователь аутентифицирован\n if (_id && accessToken) {\n console.log('[AUTH] Reconnecting WebSocket for authenticated user:', _id);\n await wsManager.reconnectWithAuth(_id);\n }\n } else {\n console.log('no cookies');\n setAuthToken(null);\n session.clear();\n this.resetState();\n }\n } catch (error) {\n console.error('Error initializing auth:', error);\n // Make sure we remove the cookie when there's an error\n await removeCookie('user');\n setAuthToken(null);\n session.clear();\n this.resetState();\n setError(error);\n throw error;\n }\n },\n\n // Helper method to reset state\n resetState() {\n state.accesses = [];\n state.user = {\n _id: undefined,\n avatar: null,\n username: '',\n email: '',\n phone: '',\n password: '',\n passwordRepeat: '',\n };\n state.access = {\n roles: null,\n token: null,\n status: false,\n };\n session.clear();\n },\n\n async login(user, type) {\n try {\n const response = await $axios.post('/api/auth/signin', {\n ...user,\n type,\n });\n\n setCookie('user', response.data);\n\n Object.assign(state.user, {\n ...response.data,\n });\n\n Object.assign(state.access, {\n token: response.data.accessToken,\n status: true,\n roles: response.data.roles,\n });\n\n session.set(response.data);\n\n await this.initialize();\n\n return response.data;\n } catch (error) {\n // Make sure cookie is removed on login error\n await removeCookie('user');\n\n Object.assign(state.access, {\n token: null,\n status: false,\n roles: null,\n });\n\n session.clear();\n\n console.log(error);\n setError(error);\n return Promise.reject(error);\n }\n },\n\n async signup(user, type, invite) {\n const { password, passwordRepeat } = state.user;\n\n console.log(password);\n console.log(passwordRepeat);\n\n if (password !== passwordRepeat) {\n const error = {\n response: {\n data: { errorCode: 'PASSWORDS_DO_NOT_MATCH' },\n },\n };\n setError(error);\n throw new Error(error.response.status);\n }\n\n try {\n const response = await $axios.post('/api/auth/signup', {\n ...user,\n type,\n inviteCode: invite,\n });\n\n console.log(response);\n\n if (response.data.accessToken) {\n setCookie('user', response.data);\n }\n\n Object.assign(state.user, {\n ...response.data,\n });\n\n Object.assign(state.access, {\n token: response.data.accessToken,\n status: true,\n roles: response.data.roles,\n });\n\n session.set(response.data);\n\n await this.initialize();\n\n return response.data;\n } catch (error) {\n // Make sure cookie is removed on signup error\n await removeCookie('user');\n setError(error);\n console.log('Sign up failed');\n throw error;\n }\n },\n\n async logout() {\n await removeCookie('user');\n setAuthToken(null);\n session.clear();\n this.resetState();\n\n // Отключаем WebSocket при выходе\n console.log('[AUTH] Disconnecting WebSocket on logout');\n wsManager.disconnect();\n },\n};\n\n// Cookies\nconst optionsDefault = {\n development: { path: '/', domain: process.env.DOMAIN_URL, secure: false, expires: 7, sameSite: 'Lax' },\n production: {\n expires: 7,\n path: '/',\n domain: process.env.DOMAIN_URL,\n sameSite: 'strict',\n secure: true,\n },\n};\n\nasync function getCookie(name) {\n if (process.env.MOBILE_APP) {\n const { value } = await Preferences.get({ key: name });\n return value ? JSON.parse(value) : null;\n } else {\n const cookie = Cookies.get(name);\n return cookie ? JSON.parse(cookie) : null;\n }\n}\n\nasync function setCookie(name, data, mode = process.env.NODE_ENV) {\n if (process.env.MOBILE_APP) {\n // Если приложение запущено в Capacitor\n await Preferences.set({\n key: name,\n value: JSON.stringify(data),\n });\n } else {\n // Для веб-версии\n const options = optionsDefault[mode];\n console.log('[AUTH COOKIE DEBUG] setCookie', { name, mode, options, domain: process.env.DOMAIN_URL });\n Cookies.set(name, JSON.stringify(data), options);\n }\n}\n\nasync function removeCookie(name, mode = process.env.NODE_ENV) {\n if (process.env.MOBILE_APP) {\n // Если приложение запущено в Capacitor\n await Preferences.remove({ key: name });\n } else {\n // Для веб-версии\n const options = optionsDefault[mode];\n const allCookiesBefore = typeof document !== 'undefined' ? document.cookie : 'SSR - no document';\n console.log('[AUTH COOKIE DEBUG] removeCookie BEFORE', { name, mode, options, domain: process.env.DOMAIN_URL, allCookies: allCookiesBefore });\n Cookies.remove(name, options);\n const allCookiesAfter = typeof document !== 'undefined' ? document.cookie : 'SSR - no document';\n console.log('[AUTH COOKIE DEBUG] removeCookie AFTER', { allCookies: allCookiesAfter });\n }\n}\n\n// History\nconst history = [];\nhistory.push(state);\n\n// Watch\nwatch(state, (newState, oldState) => {\n history.push(newState);\n});\n\n// Module Export\nexport { actions, removeCookie, state };\n"],"names":["Cookies"],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sources":["../../../../../../../src/modules/auth/views/store/auth.js"],"sourcesContent":["// Dependencies\nimport $axios, { setAuthToken } from '@martyrs/src/modules/core/views/utils/axios-instance.js';\nimport Cookies from 'js-cookie';\n// Capacitor\nimport { Preferences } from '@capacitor/preferences';\n// Vue modules\nimport { reactive, watch } from 'vue';\n// Globals\nimport { useSession, setError } from '@martyrs/src/modules/core/views/store/core.store.js';\nimport wsManager from '@martyrs/src/modules/core/views/classes/ws.manager.js';\n\n// State\nconst state = reactive({\n user: {\n _id: undefined,\n avatar: null,\n username: '',\n email: '',\n phone: '',\n password: '',\n passwordRepeat: '',\n },\n access: {\n roles: null,\n token: null,\n status: false,\n },\n accesses: [],\n});\n\n// Session manager\nconst session = useSession();\n\nconst actions = {\n async initialize(cookie) {\n try {\n const userCookie = cookie ? cookie : await getCookie('user');\n\n if (userCookie) {\n const { _id, email, phone, avatar, roles, accessToken } = userCookie;\n\n setAuthToken(accessToken);\n\n // Валидация токена (обязательно)\n await $axios.get('/api/auth/check-token');\n\n // Загрузка accesses (опционально, если модуль organizations подключен)\n let userAccesses = [];\n try {\n const response = await $axios.get('/api/organizations/check-accesses');\n userAccesses = response.data;\n } catch (error) {\n if (error.response?.status !== 404) {\n throw error;\n }\n }\n\n // ТОЛЬКО ПОСЛЕ УСПЕШНОЙ ПРОВЕРКИ устанавливаем состояние\n state.accesses = userAccesses;\n Object.assign(state.user, { _id, email, phone, avatar });\n Object.assign(state.access, { token: accessToken, roles, status: !!accessToken });\n\n // Update Session with full user data\n session.set({ ...userCookie, accesses: userAccesses });\n\n // Переподключаем WebSocket если пользователь аутентифицирован\n if (_id && accessToken) {\n console.log('[AUTH] Reconnecting WebSocket for authenticated user:', _id);\n await wsManager.reconnectWithAuth(_id);\n }\n } else {\n console.log('no cookies');\n setAuthToken(null);\n session.clear();\n this.resetState();\n }\n } catch (error) {\n console.error('Error initializing auth:', error);\n // Make sure we remove the cookie when there's an error\n await removeCookie('user');\n setAuthToken(null);\n session.clear();\n this.resetState();\n setError(error);\n throw error;\n }\n },\n\n // Helper method to reset state\n resetState() {\n state.accesses = [];\n state.user = {\n _id: undefined,\n avatar: null,\n username: '',\n email: '',\n phone: '',\n password: '',\n passwordRepeat: '',\n };\n state.access = {\n roles: null,\n token: null,\n status: false,\n };\n session.clear();\n },\n\n async login(user, type) {\n try {\n const response = await $axios.post('/api/auth/signin', {\n ...user,\n type,\n });\n\n setCookie('user', response.data);\n\n Object.assign(state.user, {\n ...response.data,\n });\n\n Object.assign(state.access, {\n token: response.data.accessToken,\n status: true,\n roles: response.data.roles,\n });\n\n session.set(response.data);\n\n await this.initialize();\n\n return response.data;\n } catch (error) {\n // Make sure cookie is removed on login error\n await removeCookie('user');\n\n Object.assign(state.access, {\n token: null,\n status: false,\n roles: null,\n });\n\n session.clear();\n\n console.log(error);\n setError(error);\n return Promise.reject(error);\n }\n },\n\n async signup(user, type, invite) {\n const { password, passwordRepeat } = state.user;\n\n console.log(password);\n console.log(passwordRepeat);\n\n if (password !== passwordRepeat) {\n const error = {\n response: {\n data: { errorCode: 'PASSWORDS_DO_NOT_MATCH' },\n },\n };\n setError(error);\n throw new Error(error.response.status);\n }\n\n try {\n const response = await $axios.post('/api/auth/signup', {\n ...user,\n type,\n inviteCode: invite,\n });\n\n console.log(response);\n\n if (response.data.accessToken) {\n setCookie('user', response.data);\n }\n\n Object.assign(state.user, {\n ...response.data,\n });\n\n Object.assign(state.access, {\n token: response.data.accessToken,\n status: true,\n roles: response.data.roles,\n });\n\n session.set(response.data);\n\n await this.initialize();\n\n return response.data;\n } catch (error) {\n // Make sure cookie is removed on signup error\n await removeCookie('user');\n setError(error);\n console.log('Sign up failed');\n throw error;\n }\n },\n\n async logout() {\n await removeCookie('user');\n setAuthToken(null);\n session.clear();\n this.resetState();\n\n // Отключаем WebSocket при выходе\n console.log('[AUTH] Disconnecting WebSocket on logout');\n wsManager.disconnect();\n },\n};\n\n// Cookies\nconst optionsDefault = {\n development: { path: '/', domain: process.env.DOMAIN_URL, secure: false, expires: 7, sameSite: 'Lax' },\n production: {\n expires: 7,\n path: '/',\n domain: process.env.DOMAIN_URL,\n sameSite: 'strict',\n secure: true,\n },\n};\n\nasync function getCookie(name) {\n if (process.env.MOBILE_APP) {\n const { value } = await Preferences.get({ key: name });\n return value ? JSON.parse(value) : null;\n } else {\n const cookie = Cookies.get(name);\n return cookie ? JSON.parse(cookie) : null;\n }\n}\n\nasync function setCookie(name, data, mode = process.env.NODE_ENV) {\n if (process.env.MOBILE_APP) {\n // Если приложение запущено в Capacitor\n await Preferences.set({\n key: name,\n value: JSON.stringify(data),\n });\n } else {\n // Для веб-версии\n const options = optionsDefault[mode];\n console.log('[AUTH COOKIE DEBUG] setCookie', { name, mode, options, domain: process.env.DOMAIN_URL });\n Cookies.set(name, JSON.stringify(data), options);\n }\n}\n\nasync function removeCookie(name, mode = process.env.NODE_ENV) {\n if (process.env.MOBILE_APP) {\n // Если приложение запущено в Capacitor\n await Preferences.remove({ key: name });\n } else {\n // Для веб-версии\n const options = optionsDefault[mode];\n const allCookiesBefore = typeof document !== 'undefined' ? document.cookie : 'SSR - no document';\n console.log('[AUTH COOKIE DEBUG] removeCookie BEFORE', { name, mode, options, domain: process.env.DOMAIN_URL, allCookies: allCookiesBefore });\n Cookies.remove(name, options);\n const allCookiesAfter = typeof document !== 'undefined' ? document.cookie : 'SSR - no document';\n console.log('[AUTH COOKIE DEBUG] removeCookie AFTER', { allCookies: allCookiesAfter });\n }\n}\n\n// History\nconst history = [];\nhistory.push(state);\n\n// Watch\nwatch(state, (newState, oldState) => {\n history.push(newState);\n});\n\n// Module Export\nexport { actions, removeCookie, state };\n"],"names":["Cookies"],"mappings":"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"}
@@ -23,14 +23,13 @@ import { default as default10 } from "./views/components/partials/NavigationBar.
23
23
  import { default as default11 } from "./views/components/partials/Sidebar.vue.js";
24
24
  import { default as default12 } from "./views/components/partials/Footer.vue.js";
25
25
  import { default as default13 } from "./views/components/sections/Walkthrough.vue.js";
26
+ import { default as default14 } from "./views/components/icons/IconMenu.vue.js";
26
27
  import { createUniversalApp } from "./views/classes/core.app.js";
27
28
  function initializeCore(app, store, router, config, options = {}) {
28
29
  const route = options.route || "Home";
29
30
  const locales = {
30
31
  en,
31
- ru,
32
- es: {}
33
- // или es: undefined
32
+ ru
34
33
  };
35
34
  i18nManager.register("core", locales);
36
35
  app.config.globalProperties.DOMAIN_URL = process.env.DOMAIN_URL;
@@ -90,6 +89,7 @@ export {
90
89
  default7 as BottomNavigationBar,
91
90
  default12 as Footer,
92
91
  default8 as Header,
92
+ default14 as IconMenu,
93
93
  default9 as Navigation,
94
94
  default10 as NavigationBar,
95
95
  default11 as Sidebar,
@@ -1 +1 @@
1
- {"version":3,"file":"core.client.js","sources":["../../../../../src/modules/core/core.client.js"],"sourcesContent":["// Functional imports (needed for initialize function)\nimport getBrowserLocale from './views/localization/get-browser-locale.js';\nimport scrollBehavior from './views/router/scrollBehavior.js';\n\nimport * as mixins from './views/mixins/mixins.js';\nimport * as storeCore from './views/store/core.store.js';\nimport { useSession, useStore } from './views/store/core.store.js';\nimport * as appRenderer from './views/utils/vue-app-renderer.js';\nimport './views/utils/polyfills.js'; // Auto-apply polyfills\n\nimport alertPlugin from './views/plugins/alert.plugin.js';\nimport datePickerPlugin from './views/plugins/date-picker.plugin.js';\nimport storeDebuggerPlugin from './views/plugins/store-debugger/store-debugger.plugin.js';\n\n\nimport { wsManager } from './views/classes/ws.manager.js';\nimport { i18nManager } from '@martyrs/src/modules/core/views/classes/i18n.manager.js';\nimport { moduleManager } from './views/classes/module.manager.js';\n\n// Будущие менеджеры:\n// import { notificationManager } from './views/classes/notification.manager.js';\n// import { alertManager } from './views/classes/alert.manager.js';\n\nimport en from './locales/en.js';\nimport ru from './locales/ru.js';\n\n\n// Core module initialization\nfunction initializeCore(app, store, router, config, options = {}) {\n const route = options.route || 'Home';\n\n const locales = {\n en: en,\n ru: ru,\n es: {} // или es: undefined\n };\n\n i18nManager.register('core', locales);\n\n const envVariables = ['NODE_ENV', 'PORT', 'APP_NAME', 'DOMAIN_URL', 'API_URL', 'WSS_URL', 'FILE_SERVER_URL', 'WDT_TOKEN', 'WDM_URL_PROD', 'GOOGLE_MAPS_API_KEY', 'MOBILE_APP'];\n\n app.config.globalProperties.DOMAIN_URL = process.env.DOMAIN_URL;\n app.config.globalProperties.API_URL = process.env.API_URL;\n app.config.globalProperties.WSS_URL = process.env.WSS_URL;\n app.config.globalProperties.MOBILE_APP = process.env.MOBILE_APP;\n app.config.globalProperties.FILE_SERVER_URL = process.env.FILE_SERVER_URL;\n app.config.globalProperties.GOOGLE_MAPS_API_KEY = process.env.GOOGLE_MAPS_API_KEY;\n\n app.mixin(mixins.globalMixins);\n\n app.use(alertPlugin);\n app.use(datePickerPlugin);\n // app.use(storeDebuggerPlugin, store);\n\n\n // WebSocket инициализируется в client.js после гидратации\n // чтобы не блокировать главный поток\n\n // Change Locale to Route Locale if available\n router.beforeEach((to, from, next) => {\n const locale = to.params.locale;\n\n if (locale) {\n if (!app.config.globalProperties.$i18n.availableLocales.includes(locale)) {\n return next({ path: '/404' });\n } else {\n app.config.globalProperties.$i18n.locale = locale;\n return next();\n }\n }\n\n return next();\n });\n\n if (config) {\n if (config.modules) store.core.state.options = config.modules;\n store.core.state.config = config;\n }\n\n // Core module is already registered by default in createStore()\n // store.addStore('core', storeCore); // Not needed anymore\n\n router.addRoute(route, {\n path: '404',\n name: 'notfound',\n component: () => import('@martyrs/src/modules/core/views/components/pages/404.vue'),\n });\n router.addRoute(route, {\n path: '401',\n name: 'unauthorized',\n component: () => import('@martyrs/src/modules/core/views/components/pages/401.vue'),\n });\n router.addRoute(route, {\n path: ':pathMatch(.*)*',\n name: 'NotFound',\n redirect: { name: 'notfound' },\n });\n}\n\nconst ModuleCore = {\n initialize: initializeCore,\n views: {\n store: {\n storeCore,\n },\n router: {\n // routerCore\n },\n },\n};\n\n// Component re-exports (enables tree shaking)\nexport { default as layoutApp } from './views/components/layouts/App.vue';\nexport { default as layoutClient } from './views/components/layouts/Client.vue';\nexport { default as BlockSearch } from '@martyrs/src/modules/core/views/components/blocks/BlockSearch.vue';\nexport { default as BottomNavigationBar } from '@martyrs/src/modules/core/views/components/partials/BottomNavigationBar.vue';\nexport { default as Header } from '@martyrs/src/modules/core/views/components/partials/Header.vue';\nexport { default as Navigation } from '@martyrs/src/modules/core/views/components/partials/Navigation.vue';\nexport { default as NavigationBar } from '@martyrs/src/modules/core/views/components/partials/NavigationBar.vue';\nexport { default as Sidebar } from '@martyrs/src/modules/core/views/components/partials/Sidebar.vue';\nexport { default as Footer } from '@martyrs/src/modules/core/views/components/partials/Footer.vue';\nexport { default as Walkthrough } from '@martyrs/src/modules/core/views/components/sections/Walkthrough.vue';\n\n\n// Functional exports\nexport {\n appRenderer,\n getBrowserLocale,\n mixins,\n moduleManager,\n scrollBehavior,\n i18nManager,\n storeCore,\n useSession,\n useStore,\n wsManager,\n};\n\n// Export client factory\nexport { createUniversalApp } from './views/classes/core.app.js';\n\n// Re-export polyfills for documentation\nexport * from './views/utils/polyfills.js';\n\nexport default ModuleCore;\n"],"names":["mixins.globalMixins","storeCore"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAS,eAAe,KAAK,OAAO,QAAQ,QAAQ,UAAU,IAAI;AAChE,QAAM,QAAQ,QAAQ,SAAS;AAE/B,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,IAAI,CAAA;AAAA;AAAA,EACR;AAEE,cAAY,SAAS,QAAQ,OAAO;AAIpC,MAAI,OAAO,iBAAiB,aAAa,QAAQ,IAAI;AACrD,MAAI,OAAO,iBAAiB,UAAU,QAAQ,IAAI;AAClD,MAAI,OAAO,iBAAiB,UAAU,QAAQ,IAAI;AAClD,MAAI,OAAO,iBAAiB,aAAa,QAAQ,IAAI;AACrD,MAAI,OAAO,iBAAiB,kBAAkB,QAAQ,IAAI;AAC1D,MAAI,OAAO,iBAAiB,sBAAsB,QAAQ,IAAI;AAE9D,MAAI,MAAMA,YAAmB;AAE7B,MAAI,IAAI,WAAW;AACnB,MAAI,IAAI,gBAAgB;AAQxB,SAAO,WAAW,CAAC,IAAI,MAAM,SAAS;AACpC,UAAM,SAAS,GAAG,OAAO;AAEzB,QAAI,QAAQ;AACV,UAAI,CAAC,IAAI,OAAO,iBAAiB,MAAM,iBAAiB,SAAS,MAAM,GAAG;AACxE,eAAO,KAAK,EAAE,MAAM,QAAQ;AAAA,MAC9B,OAAO;AACL,YAAI,OAAO,iBAAiB,MAAM,SAAS;AAC3C,eAAO,KAAI;AAAA,MACb;AAAA,IACF;AAEA,WAAO,KAAI;AAAA,EACb,CAAC;AAED,MAAI,QAAQ;AACV,QAAI,OAAO,QAAS,OAAM,KAAK,MAAM,UAAU,OAAO;AACtD,UAAM,KAAK,MAAM,SAAS;AAAA,EAC5B;AAKA,SAAO,SAAS,OAAO;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW,MAAM,OAAO,qCAA0D;AAAA,EACtF,CAAG;AACD,SAAO,SAAS,OAAO;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW,MAAM,OAAO,qCAA0D;AAAA,EACtF,CAAG;AACD,SAAO,SAAS,OAAO;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU,EAAE,MAAM,WAAU;AAAA,EAChC,CAAG;AACH;AAEK,MAAC,aAAa;AAAA,EACjB,YAAY;AAAA,EACZ,OAAO;AAAA,IACL,OAAO;AAAA,MACX,WAAMC;AAAAA,IACN;AAAA,IACI,QAAQ;AAAA;AAAA,IAEZ;AAAA,EACA;AACA;"}
1
+ {"version":3,"file":"core.client.js","sources":["../../../../../src/modules/core/core.client.js"],"sourcesContent":["// Functional imports (needed for initialize function)\nimport getBrowserLocale from './views/localization/get-browser-locale.js';\nimport scrollBehavior from './views/router/scrollBehavior.js';\n\nimport * as mixins from './views/mixins/mixins.js';\nimport * as storeCore from './views/store/core.store.js';\nimport { useSession, useStore } from './views/store/core.store.js';\nimport * as appRenderer from './views/utils/vue-app-renderer.js';\nimport './views/utils/polyfills.js'; // Auto-apply polyfills\n\nimport alertPlugin from './views/plugins/alert.plugin.js';\nimport datePickerPlugin from './views/plugins/date-picker.plugin.js';\nimport storeDebuggerPlugin from './views/plugins/store-debugger/store-debugger.plugin.js';\n\n\nimport { wsManager } from './views/classes/ws.manager.js';\nimport { i18nManager } from '@martyrs/src/modules/core/views/classes/i18n.manager.js';\nimport { moduleManager } from './views/classes/module.manager.js';\n\n// Будущие менеджеры:\n// import { notificationManager } from './views/classes/notification.manager.js';\n// import { alertManager } from './views/classes/alert.manager.js';\n\nimport en from './locales/en.js';\nimport ru from './locales/ru.js';\n\n\n// Core module initialization\nfunction initializeCore(app, store, router, config, options = {}) {\n const route = options.route || 'Home';\n\n const locales = {\n en: en,\n ru: ru\n };\n\n i18nManager.register('core', locales);\n\n const envVariables = ['NODE_ENV', 'PORT', 'APP_NAME', 'DOMAIN_URL', 'API_URL', 'WSS_URL', 'FILE_SERVER_URL', 'WDT_TOKEN', 'WDM_URL_PROD', 'GOOGLE_MAPS_API_KEY', 'MOBILE_APP'];\n\n app.config.globalProperties.DOMAIN_URL = process.env.DOMAIN_URL;\n app.config.globalProperties.API_URL = process.env.API_URL;\n app.config.globalProperties.WSS_URL = process.env.WSS_URL;\n app.config.globalProperties.MOBILE_APP = process.env.MOBILE_APP;\n app.config.globalProperties.FILE_SERVER_URL = process.env.FILE_SERVER_URL;\n app.config.globalProperties.GOOGLE_MAPS_API_KEY = process.env.GOOGLE_MAPS_API_KEY;\n\n app.mixin(mixins.globalMixins);\n\n app.use(alertPlugin);\n app.use(datePickerPlugin);\n // app.use(storeDebuggerPlugin, store);\n\n\n // WebSocket инициализируется в client.js после гидратации\n // чтобы не блокировать главный поток\n\n // Change Locale to Route Locale if available\n router.beforeEach((to, from, next) => {\n const locale = to.params.locale;\n\n if (locale) {\n if (!app.config.globalProperties.$i18n.availableLocales.includes(locale)) {\n return next({ path: '/404' });\n } else {\n app.config.globalProperties.$i18n.locale = locale;\n return next();\n }\n }\n\n return next();\n });\n\n if (config) {\n if (config.modules) store.core.state.options = config.modules;\n store.core.state.config = config;\n }\n\n // Core module is already registered by default in createStore()\n // store.addStore('core', storeCore); // Not needed anymore\n\n router.addRoute(route, {\n path: '404',\n name: 'notfound',\n component: () => import('@martyrs/src/modules/core/views/components/pages/404.vue'),\n });\n router.addRoute(route, {\n path: '401',\n name: 'unauthorized',\n component: () => import('@martyrs/src/modules/core/views/components/pages/401.vue'),\n });\n router.addRoute(route, {\n path: ':pathMatch(.*)*',\n name: 'NotFound',\n redirect: { name: 'notfound' },\n });\n}\n\nconst ModuleCore = {\n initialize: initializeCore,\n views: {\n store: {\n storeCore,\n },\n router: {\n // routerCore\n },\n },\n};\n\n// Component re-exports (enables tree shaking)\nexport { default as layoutApp } from './views/components/layouts/App.vue';\nexport { default as layoutClient } from './views/components/layouts/Client.vue';\nexport { default as BlockSearch } from '@martyrs/src/modules/core/views/components/blocks/BlockSearch.vue';\nexport { default as BottomNavigationBar } from '@martyrs/src/modules/core/views/components/partials/BottomNavigationBar.vue';\nexport { default as Header } from '@martyrs/src/modules/core/views/components/partials/Header.vue';\nexport { default as Navigation } from '@martyrs/src/modules/core/views/components/partials/Navigation.vue';\nexport { default as NavigationBar } from '@martyrs/src/modules/core/views/components/partials/NavigationBar.vue';\nexport { default as Sidebar } from '@martyrs/src/modules/core/views/components/partials/Sidebar.vue';\nexport { default as Footer } from '@martyrs/src/modules/core/views/components/partials/Footer.vue';\nexport { default as Walkthrough } from '@martyrs/src/modules/core/views/components/sections/Walkthrough.vue';\nexport { default as IconMenu } from '@martyrs/src/modules/core/views/components/icons/IconMenu.vue';\n\n\n// Functional exports\nexport {\n appRenderer,\n getBrowserLocale,\n mixins,\n moduleManager,\n scrollBehavior,\n i18nManager,\n storeCore,\n useSession,\n useStore,\n wsManager,\n};\n\n// Export client factory\nexport { createUniversalApp } from './views/classes/core.app.js';\n\n// Re-export polyfills for documentation\nexport * from './views/utils/polyfills.js';\n\nexport default ModuleCore;\n"],"names":["mixins.globalMixins","storeCore"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAS,eAAe,KAAK,OAAO,QAAQ,QAAQ,UAAU,IAAI;AAChE,QAAM,QAAQ,QAAQ,SAAS;AAE/B,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,EACJ;AAEE,cAAY,SAAS,QAAQ,OAAO;AAIpC,MAAI,OAAO,iBAAiB,aAAa,QAAQ,IAAI;AACrD,MAAI,OAAO,iBAAiB,UAAU,QAAQ,IAAI;AAClD,MAAI,OAAO,iBAAiB,UAAU,QAAQ,IAAI;AAClD,MAAI,OAAO,iBAAiB,aAAa,QAAQ,IAAI;AACrD,MAAI,OAAO,iBAAiB,kBAAkB,QAAQ,IAAI;AAC1D,MAAI,OAAO,iBAAiB,sBAAsB,QAAQ,IAAI;AAE9D,MAAI,MAAMA,YAAmB;AAE7B,MAAI,IAAI,WAAW;AACnB,MAAI,IAAI,gBAAgB;AAQxB,SAAO,WAAW,CAAC,IAAI,MAAM,SAAS;AACpC,UAAM,SAAS,GAAG,OAAO;AAEzB,QAAI,QAAQ;AACV,UAAI,CAAC,IAAI,OAAO,iBAAiB,MAAM,iBAAiB,SAAS,MAAM,GAAG;AACxE,eAAO,KAAK,EAAE,MAAM,QAAQ;AAAA,MAC9B,OAAO;AACL,YAAI,OAAO,iBAAiB,MAAM,SAAS;AAC3C,eAAO,KAAI;AAAA,MACb;AAAA,IACF;AAEA,WAAO,KAAI;AAAA,EACb,CAAC;AAED,MAAI,QAAQ;AACV,QAAI,OAAO,QAAS,OAAM,KAAK,MAAM,UAAU,OAAO;AACtD,UAAM,KAAK,MAAM,SAAS;AAAA,EAC5B;AAKA,SAAO,SAAS,OAAO;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW,MAAM,OAAO,qCAA0D;AAAA,EACtF,CAAG;AACD,SAAO,SAAS,OAAO;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,WAAW,MAAM,OAAO,qCAA0D;AAAA,EACtF,CAAG;AACD,SAAO,SAAS,OAAO;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU,EAAE,MAAM,WAAU;AAAA,EAChC,CAAG;AACH;AAEK,MAAC,aAAa;AAAA,EACjB,YAAY;AAAA,EACZ,OAAO;AAAA,IACL,OAAO;AAAA,MACX,WAAMC;AAAAA,IACN;AAAA,IACI,QAAQ;AAAA;AAAA,IAEZ;AAAA,EACA;AACA;"}
@@ -22,7 +22,7 @@ const _sfc_main = {
22
22
  if (!wsManager.isConnected) return;
23
23
  }
24
24
  try {
25
- const result = await wsManager.rpc("core", "getOnlineStatus", { userId: props.userId });
25
+ const result = await wsManager.rpc("auth", "getOnlineStatus", { userId: props.userId });
26
26
  console.log("[OnlineIndicator] status:", result);
27
27
  isOnline.value = result.isOnline;
28
28
  lastSeenAt.value = result.lastSeenAt;
@@ -1 +1 @@
1
- {"version":3,"file":"OnlineIndicator.vue.js","sources":["../../../../../../../../src/modules/core/views/components/elements/OnlineIndicator.vue"],"sourcesContent":["<template>\n <Tooltip :text=\"isOnline ? 'Online' : (lastSeenAt ? formatLastSeen(lastSeenAt) : 'Offline')\">\n <div\n class=\"i-medium online-indicator\"\n :class=\"{ 'is-online': isOnline }\"\n />\n </Tooltip>\n</template>\n\n<script setup>\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport Tooltip from '@martyrs/src/components/Tooltip/Tooltip.vue';\nimport wsManager from '@martyrs/src/modules/core/views/classes/ws.manager.js';\n\nconst props = defineProps({\n userId: {\n type: String,\n required: true,\n },\n});\n\nconst isOnline = ref(false);\nconst lastSeenAt = ref(null);\nlet pollInterval = null;\n\nasync function fetchStatus() {\n if (!props.userId) return;\n // Ждем подключения если еще не подключен\n if (!wsManager.isConnected) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n if (!wsManager.isConnected) return;\n }\n try {\n const result = await wsManager.rpc('core', 'getOnlineStatus', { userId: props.userId });\n console.log('[OnlineIndicator] status:', result);\n isOnline.value = result.isOnline;\n lastSeenAt.value = result.lastSeenAt;\n } catch (err) {\n console.error('Failed to fetch online status:', err);\n }\n}\n\nfunction formatLastSeen(date) {\n if (!date) return '';\n const d = new Date(date);\n const now = new Date();\n const diff = now - d;\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(diff / 3600000);\n const days = Math.floor(diff / 86400000);\n\n if (minutes < 1) return 'Just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) return `${hours}h ago`;\n if (days < 7) return `${days}d ago`;\n return d.toLocaleDateString();\n}\n\nonMounted(() => {\n fetchStatus();\n pollInterval = setInterval(fetchStatus, 60000);\n});\n\nonUnmounted(() => {\n if (pollInterval) clearInterval(pollInterval);\n});\n\nwatch(() => props.userId, () => {\n fetchStatus();\n});\n</script>\n\n<style lang=\"scss\">\n.online-indicator {\n position: relative;\n border-radius: 50%;\n background: rgb(var(--grey));\n border: 3px solid rgb(var(--light));\n flex-shrink: 0;\n\n &.is-online {\n background: rgb(var(--green));\n\n &::before,\n &::after {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n width: 100%;\n height: 100%;\n background: inherit;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n animation: indicator-pulse 2s infinite ease-out;\n }\n\n &::after {\n animation-delay: 1s;\n }\n }\n\n}\n\n@keyframes indicator-pulse {\n 0% {\n transform: translate(-50%, -50%) scale(1);\n opacity: 0.5;\n }\n 100% {\n transform: translate(-50%, -50%) scale(1.8);\n opacity: 0;\n }\n}\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;AAcA,UAAM,QAAQ;AAOd,UAAM,WAAW,IAAI,KAAK;AAC1B,UAAM,aAAa,IAAI,IAAI;AAC3B,QAAI,eAAe;AAEnB,mBAAe,cAAc;AAC3B,UAAI,CAAC,MAAM,OAAQ;AAEnB,UAAI,CAAC,UAAU,aAAa;AAC1B,cAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAI,CAAC;AACtD,YAAI,CAAC,UAAU,YAAa;AAAA,MAC9B;AACA,UAAI;AACF,cAAM,SAAS,MAAM,UAAU,IAAI,QAAQ,mBAAmB,EAAE,QAAQ,MAAM,QAAQ;AACtF,gBAAQ,IAAI,6BAA6B,MAAM;AAC/C,iBAAS,QAAQ,OAAO;AACxB,mBAAW,QAAQ,OAAO;AAAA,MAC5B,SAAS,KAAK;AACZ,gBAAQ,MAAM,kCAAkC,GAAG;AAAA,MACrD;AAAA,IACF;AAEA,aAAS,eAAe,MAAM;AAC5B,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,IAAI,IAAI,KAAK,IAAI;AACvB,YAAM,MAAM,oBAAI,KAAI;AACpB,YAAM,OAAO,MAAM;AACnB,YAAM,UAAU,KAAK,MAAM,OAAO,GAAK;AACvC,YAAM,QAAQ,KAAK,MAAM,OAAO,IAAO;AACvC,YAAM,OAAO,KAAK,MAAM,OAAO,KAAQ;AAEvC,UAAI,UAAU,EAAG,QAAO;AACxB,UAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AACnC,UAAI,QAAQ,GAAI,QAAO,GAAG,KAAK;AAC/B,UAAI,OAAO,EAAG,QAAO,GAAG,IAAI;AAC5B,aAAO,EAAE,mBAAkB;AAAA,IAC7B;AAEA,cAAU,MAAM;AACd,kBAAW;AACX,qBAAe,YAAY,aAAa,GAAK;AAAA,IAC/C,CAAC;AAED,gBAAY,MAAM;AAChB,UAAI,aAAc,eAAc,YAAY;AAAA,IAC9C,CAAC;AAED,UAAM,MAAM,MAAM,QAAQ,MAAM;AAC9B,kBAAW;AAAA,IACb,CAAC;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"OnlineIndicator.vue.js","sources":["../../../../../../../../src/modules/core/views/components/elements/OnlineIndicator.vue"],"sourcesContent":["<template>\n <Tooltip :text=\"isOnline ? 'Online' : (lastSeenAt ? formatLastSeen(lastSeenAt) : 'Offline')\">\n <div\n class=\"i-medium online-indicator\"\n :class=\"{ 'is-online': isOnline }\"\n />\n </Tooltip>\n</template>\n\n<script setup>\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport Tooltip from '@martyrs/src/components/Tooltip/Tooltip.vue';\nimport wsManager from '@martyrs/src/modules/core/views/classes/ws.manager.js';\n\nconst props = defineProps({\n userId: {\n type: String,\n required: true,\n },\n});\n\nconst isOnline = ref(false);\nconst lastSeenAt = ref(null);\nlet pollInterval = null;\n\nasync function fetchStatus() {\n if (!props.userId) return;\n // Ждем подключения если еще не подключен\n if (!wsManager.isConnected) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n if (!wsManager.isConnected) return;\n }\n try {\n const result = await wsManager.rpc('auth', 'getOnlineStatus', { userId: props.userId });\n console.log('[OnlineIndicator] status:', result);\n isOnline.value = result.isOnline;\n lastSeenAt.value = result.lastSeenAt;\n } catch (err) {\n console.error('Failed to fetch online status:', err);\n }\n}\n\nfunction formatLastSeen(date) {\n if (!date) return '';\n const d = new Date(date);\n const now = new Date();\n const diff = now - d;\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(diff / 3600000);\n const days = Math.floor(diff / 86400000);\n\n if (minutes < 1) return 'Just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) return `${hours}h ago`;\n if (days < 7) return `${days}d ago`;\n return d.toLocaleDateString();\n}\n\nonMounted(() => {\n fetchStatus();\n pollInterval = setInterval(fetchStatus, 60000);\n});\n\nonUnmounted(() => {\n if (pollInterval) clearInterval(pollInterval);\n});\n\nwatch(() => props.userId, () => {\n fetchStatus();\n});\n</script>\n\n<style lang=\"scss\">\n.online-indicator {\n position: relative;\n border-radius: 50%;\n background: rgb(var(--grey));\n border: 3px solid rgb(var(--light));\n flex-shrink: 0;\n\n &.is-online {\n background: rgb(var(--green));\n\n &::before,\n &::after {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n width: 100%;\n height: 100%;\n background: inherit;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n animation: indicator-pulse 2s infinite ease-out;\n }\n\n &::after {\n animation-delay: 1s;\n }\n }\n\n}\n\n@keyframes indicator-pulse {\n 0% {\n transform: translate(-50%, -50%) scale(1);\n opacity: 0.5;\n }\n 100% {\n transform: translate(-50%, -50%) scale(1.8);\n opacity: 0;\n }\n}\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;AAcA,UAAM,QAAQ;AAOd,UAAM,WAAW,IAAI,KAAK;AAC1B,UAAM,aAAa,IAAI,IAAI;AAC3B,QAAI,eAAe;AAEnB,mBAAe,cAAc;AAC3B,UAAI,CAAC,MAAM,OAAQ;AAEnB,UAAI,CAAC,UAAU,aAAa;AAC1B,cAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAI,CAAC;AACtD,YAAI,CAAC,UAAU,YAAa;AAAA,MAC9B;AACA,UAAI;AACF,cAAM,SAAS,MAAM,UAAU,IAAI,QAAQ,mBAAmB,EAAE,QAAQ,MAAM,QAAQ;AACtF,gBAAQ,IAAI,6BAA6B,MAAM;AAC/C,iBAAS,QAAQ,OAAO;AACxB,mBAAW,QAAQ,OAAO;AAAA,MAC5B,SAAS,KAAK;AACZ,gBAAQ,MAAM,kCAAkC,GAAG;AAAA,MACrD;AAAA,IACF;AAEA,aAAS,eAAe,MAAM;AAC5B,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,IAAI,IAAI,KAAK,IAAI;AACvB,YAAM,MAAM,oBAAI,KAAI;AACpB,YAAM,OAAO,MAAM;AACnB,YAAM,UAAU,KAAK,MAAM,OAAO,GAAK;AACvC,YAAM,QAAQ,KAAK,MAAM,OAAO,IAAO;AACvC,YAAM,OAAO,KAAK,MAAM,OAAO,KAAQ;AAEvC,UAAI,UAAU,EAAG,QAAO;AACxB,UAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AACnC,UAAI,QAAQ,GAAI,QAAO,GAAG,KAAK;AAC/B,UAAI,OAAO,EAAG,QAAO,GAAG,IAAI;AAC5B,aAAO,EAAE,mBAAkB;AAAA,IAC7B;AAEA,cAAU,MAAM;AACd,kBAAW;AACX,qBAAe,YAAY,aAAa,GAAK;AAAA,IAC/C,CAAC;AAED,gBAAY,MAAM;AAChB,UAAI,aAAc,eAAc,YAAY;AAAA,IAC9C,CAAC;AAED,UAAM,MAAM,MAAM,QAAQ,MAAM;AAC9B,kBAAW;AAAA,IACb,CAAC;;;;;;;;;;;;;;;"}
@@ -0,0 +1,44 @@
1
+ import { createElementBlock, openBlock, normalizeClass, createElementVNode } from "vue";
2
+ /* empty css */
3
+ const _sfc_main = {
4
+ __name: "IconMenu",
5
+ props: {
6
+ active: {
7
+ type: Boolean,
8
+ default: false
9
+ },
10
+ theme: {
11
+ type: String,
12
+ default: "light"
13
+ }
14
+ },
15
+ emits: ["click"],
16
+ setup(__props, { emit: __emit }) {
17
+ const emit = __emit;
18
+ return (_ctx, _cache) => {
19
+ return openBlock(), createElementBlock("button", {
20
+ class: normalizeClass(["cursor-pointer mobile-only icon-menu", { "icon-menu_active": __props.active }]),
21
+ "aria-label": "menu",
22
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("click"))
23
+ }, [
24
+ createElementVNode("span", {
25
+ class: normalizeClass(["no-events", {
26
+ "bg-black": __props.theme === "light",
27
+ "bg-white": __props.theme === "dark"
28
+ }])
29
+ }, [
30
+ createElementVNode("span", {
31
+ class: normalizeClass(["icon-menu__before", { "bg-black": __props.theme === "light", "bg-white": __props.theme === "dark" }])
32
+ }, null, 2),
33
+ createElementVNode("span", {
34
+ class: normalizeClass(["icon-menu__after", { "bg-black": __props.theme === "light", "bg-white": __props.theme === "dark" }])
35
+ }, null, 2)
36
+ ], 2)
37
+ ], 2);
38
+ };
39
+ }
40
+ };
41
+ export {
42
+ _sfc_main as default
43
+ };
44
+ //# sourceMappingURL=IconMenu.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IconMenu.vue.js","sources":["../../../../../../../../src/modules/core/views/components/icons/IconMenu.vue"],"sourcesContent":["<script setup>\ndefineProps({\n active: {\n type: Boolean,\n default: false,\n },\n theme: {\n type: String,\n default: 'light',\n },\n});\n\nconst emit = defineEmits(['click']);\n</script>\n\n<template>\n <button\n class=\"cursor-pointer mobile-only icon-menu\"\n aria-label=\"menu\"\n :class=\"{ 'icon-menu_active': active }\"\n @click=\"emit('click')\"\n >\n <span\n class=\"no-events\"\n :class=\"{\n 'bg-black': theme === 'light',\n 'bg-white': theme === 'dark',\n }\"\n >\n <span class=\"icon-menu__before\" :class=\"{ 'bg-black': theme === 'light', 'bg-white': theme === 'dark' }\"></span>\n <span class=\"icon-menu__after\" :class=\"{ 'bg-black': theme === 'light', 'bg-white': theme === 'dark' }\"></span>\n </span>\n </button>\n</template>\n\n<style lang=\"scss\">\n.icon-menu {\n display: block;\n width: 2rem;\n height: 2rem;\n border-radius: 50%;\n position: relative;\n}\n\n.icon-menu span,\n.icon-menu__before,\n.icon-menu__after {\n position: absolute;\n top: 50%;\n margin-top: -1px;\n left: 50%;\n margin-left: -10px;\n width: 20px;\n height: 2px;\n}\n\n.icon-menu__before,\n.icon-menu__after {\n display: block;\n transition: 0.2s;\n}\n\n.icon-menu__before {\n transform: translateY(-5px);\n}\n\n.icon-menu__after {\n transform: translateY(5px);\n}\n\n.icon-menu_active .icon-menu__before {\n transform: rotate(-35deg);\n width: 10px;\n transform-origin: left bottom;\n}\n\n.icon-menu_active .icon-menu__after {\n transform: rotate(35deg);\n width: 10px;\n transform-origin: left top;\n}\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAYA,UAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;"}