auth.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { defineStore } from "pinia";
  2. import { ref } from "vue";
  3. import { getCurrentUser } from "@/lib/api";
  4. export const useAuthStore = defineStore("auth", () => {
  5. const user = ref<any>(null);
  6. const isLoading = ref(true);
  7. const showCompleteProfile = ref(false);
  8. let initialized = false;
  9. async function refreshUser() {
  10. try {
  11. const userData = await getCurrentUser();
  12. user.value = userData;
  13. showCompleteProfile.value = !!(
  14. userData && (!userData.phone || !userData.shipping_address)
  15. );
  16. } catch {
  17. user.value = null;
  18. showCompleteProfile.value = false;
  19. stopPing();
  20. } finally {
  21. isLoading.value = false;
  22. if (user.value && !pingInterval) startPing();
  23. }
  24. }
  25. let pingInterval: number | null = null;
  26. const unreadMessagesCount = ref(0);
  27. function playNotificationSound() {
  28. try {
  29. const AudioCtx = window.AudioContext || (window as any).webkitAudioContext;
  30. if (!AudioCtx) return;
  31. const ctx = new AudioCtx();
  32. const osc = ctx.createOscillator();
  33. const gainNode = ctx.createGain();
  34. osc.type = 'sine';
  35. osc.frequency.setValueAtTime(880, ctx.currentTime); // A5
  36. osc.frequency.exponentialRampToValueAtTime(1760, ctx.currentTime + 0.1); // Up to A6
  37. gainNode.gain.setValueAtTime(0, ctx.currentTime);
  38. gainNode.gain.linearRampToValueAtTime(0.1, ctx.currentTime + 0.05);
  39. gainNode.gain.linearRampToValueAtTime(0, ctx.currentTime + 0.2);
  40. osc.connect(gainNode);
  41. gainNode.connect(ctx.destination);
  42. osc.start();
  43. osc.stop(ctx.currentTime + 0.2);
  44. } catch (e) {
  45. console.warn("Audio disabled or not supported", e);
  46. }
  47. }
  48. function startPing() {
  49. import("@/lib/api").then(({ authPing }) => {
  50. const doPing = async () => {
  51. const res = await authPing();
  52. if (res && res.unread_count !== undefined) {
  53. if (res.unread_count > unreadMessagesCount.value) {
  54. playNotificationSound();
  55. }
  56. unreadMessagesCount.value = res.unread_count;
  57. }
  58. };
  59. doPing(); // ping immediately
  60. pingInterval = window.setInterval(doPing, 30000);
  61. });
  62. }
  63. function stopPing() {
  64. if (pingInterval) {
  65. clearInterval(pingInterval);
  66. pingInterval = null;
  67. }
  68. }
  69. function init() {
  70. if (!initialized) {
  71. initialized = true;
  72. refreshUser();
  73. }
  74. }
  75. function setUser(u: any) {
  76. user.value = u;
  77. }
  78. function onProfileComplete() {
  79. showCompleteProfile.value = false;
  80. refreshUser();
  81. }
  82. async function logout() {
  83. import("@/lib/api").then(async ({ logoutUser }) => {
  84. await logoutUser();
  85. localStorage.removeItem("token");
  86. user.value = null;
  87. unreadMessagesCount.value = 0;
  88. stopPing();
  89. });
  90. }
  91. return {
  92. user,
  93. isLoading,
  94. showCompleteProfile,
  95. unreadMessagesCount,
  96. init,
  97. setUser,
  98. refreshUser,
  99. onProfileComplete,
  100. logout,
  101. };
  102. });