feat(auth): include subscription tier in token and session payload
- Adds subscription tier info to access/refresh tokens. - Stores tier details in session Redis record. - Returns tier data in login/register response. - Uses default tier when user has none.
This commit is contained in:
1 parent
7f42def478
commit
d27526e026
20 files changed
+2133
-40
No files matched your search
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { Bell } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
@@ -33,10 +33,32 @@ export function NotificationBell({ userId, className }: NotificationBellProps) {
|
||||
const [notifications, setNotifications] = useState<Notification[]>([]);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const rawUnreadRef = useRef(0);
|
||||
const baselineUnreadRef = useRef(0);
|
||||
const baselineLoadedRef = useRef(false);
|
||||
const storageKeyRef = useRef<string | null>(null);
|
||||
|
||||
const effectiveUserId = userId || user?.userId;
|
||||
|
||||
// Buscar contagem de não lidas
|
||||
const persistBaseline = (value: number) => {
|
||||
baselineUnreadRef.current = value;
|
||||
if (typeof window !== "undefined" && storageKeyRef.current) {
|
||||
window.localStorage.setItem(storageKeyRef.current, String(value));
|
||||
}
|
||||
};
|
||||
|
||||
const loadBaselineFromStorage = () => {
|
||||
if (typeof window === "undefined" || !storageKeyRef.current) {
|
||||
return undefined;
|
||||
}
|
||||
const stored = window.localStorage.getItem(storageKeyRef.current);
|
||||
if (!stored) return undefined;
|
||||
const parsed = Number.parseInt(stored, 10);
|
||||
if (Number.isNaN(parsed)) return undefined;
|
||||
return parsed;
|
||||
};
|
||||
|
||||
const fetchUnreadCount = async () => {
|
||||
if (!effectiveUserId) return;
|
||||
|
||||
@@ -45,7 +67,20 @@ export function NotificationBell({ userId, className }: NotificationBellProps) {
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
setUnreadCount(data.count);
|
||||
rawUnreadRef.current = data.count;
|
||||
if (!baselineLoadedRef.current) {
|
||||
const storedBaseline = loadBaselineFromStorage();
|
||||
if (storedBaseline !== undefined) {
|
||||
const normalized = Math.min(storedBaseline, data.count);
|
||||
persistBaseline(normalized);
|
||||
} else {
|
||||
persistBaseline(data.count);
|
||||
}
|
||||
baselineLoadedRef.current = true;
|
||||
} else if (data.count < baselineUnreadRef.current) {
|
||||
persistBaseline(data.count);
|
||||
}
|
||||
setUnreadCount(Math.max(0, data.count - baselineUnreadRef.current));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -74,6 +109,21 @@ export function NotificationBell({ userId, className }: NotificationBellProps) {
|
||||
};
|
||||
|
||||
// Polling automático a cada 30 segundos
|
||||
useEffect(() => {
|
||||
if (!effectiveUserId) {
|
||||
return;
|
||||
}
|
||||
storageKeyRef.current = `notifications:lastBaseline:${effectiveUserId}`;
|
||||
const storedBaseline = loadBaselineFromStorage();
|
||||
if (storedBaseline !== undefined) {
|
||||
baselineUnreadRef.current = storedBaseline;
|
||||
baselineLoadedRef.current = true;
|
||||
} else {
|
||||
baselineUnreadRef.current = 0;
|
||||
baselineLoadedRef.current = false;
|
||||
}
|
||||
}, [effectiveUserId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!effectiveUserId) return;
|
||||
|
||||
@@ -94,6 +144,8 @@ export function NotificationBell({ userId, className }: NotificationBellProps) {
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
fetchNotifications();
|
||||
persistBaseline(rawUnreadRef.current);
|
||||
setUnreadCount(0);
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
@@ -111,6 +163,12 @@ export function NotificationBell({ userId, className }: NotificationBellProps) {
|
||||
)
|
||||
);
|
||||
// Atualizar contagem
|
||||
rawUnreadRef.current = Math.max(0, rawUnreadRef.current - 1);
|
||||
const newBaseline = Math.min(
|
||||
baselineUnreadRef.current,
|
||||
rawUnreadRef.current
|
||||
);
|
||||
persistBaseline(newBaseline);
|
||||
setUnreadCount((prev) => Math.max(0, prev - 1));
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in new issue
Block a user