From e7ce2fa54b843fbe721f288dc723b94e87113b10 Mon Sep 17 00:00:00 2001 From: Antoine Dewez <44063631+Zewed@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:44:48 +0200 Subject: [PATCH] feat(frontend): show remaining credits (#2495) # Description Please include a summary of the changes and the related issue. Please also include relevant motivation and context. ## Checklist before requesting a review Please delete options that are not relevant. - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented hard-to-understand areas - [ ] I have ideally added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged ## Screenshots (if appropriate): --- backend/modules/chat/controller/chat/utils.py | 2 +- .../modules/user/controller/user_controller.py | 13 +++++++++++++ backend/modules/user/repository/users.py | 10 ++++++++++ .../modules/user/repository/users_interface.py | 7 +++++++ backend/modules/user/service/user_usage.py | 2 +- frontend/app/chat/[chatId]/hooks/useChat.ts | 8 ++++++++ frontend/app/search/page.module.scss | 16 ++++++++++++++++ frontend/app/search/page.tsx | 18 ++++++++++++++---- frontend/lib/api/user/useUserApi.ts | 2 ++ frontend/lib/api/user/user.ts | 4 ++++ .../PageHeader/PageHeader.module.scss | 13 ++++++++++++- .../lib/components/PageHeader/PageHeader.tsx | 16 ++++++++++++++++ .../User-settings.provider.tsx | 14 ++++++++++++++ frontend/lib/helpers/iconList.ts | 2 ++ 14 files changed, 120 insertions(+), 7 deletions(-) diff --git a/backend/modules/chat/controller/chat/utils.py b/backend/modules/chat/controller/chat/utils.py index ea7eee95a..9632e7ddd 100644 --- a/backend/modules/chat/controller/chat/utils.py +++ b/backend/modules/chat/controller/chat/utils.py @@ -98,7 +98,7 @@ def update_user_usage(usage: UserUsage, user_settings, cost: int = 100): if int(montly_usage + cost) > int(monthly_chat_credit): raise HTTPException( status_code=429, # pyright: ignore reportPrivateUsage=none - detail=f"You have reached your monthly chat limit of {monthly_chat_credit} requests per months. Please upgrade your plan to increase your daily chat limit.", + detail=f"You have reached your monthly chat limit of {monthly_chat_credit} requests per months. Please upgrade your plan to increase your monthly chat limit.", ) else: usage.handle_increment_user_request_count(date, cost) diff --git a/backend/modules/user/controller/user_controller.py b/backend/modules/user/controller/user_controller.py index a70b3e25e..716b5983d 100644 --- a/backend/modules/user/controller/user_controller.py +++ b/backend/modules/user/controller/user_controller.py @@ -78,3 +78,16 @@ def get_user_identity_route( Get user identity. """ return user_repository.get_user_identity(current_user.id) + +@user_router.get( + "/user/credits", + dependencies=[Depends(AuthBearer())], + tags=["User"], +) +def get_user_credits( + current_user: UserIdentity = Depends(get_current_user), +) -> int: + """ + Get user remaining credits. + """ + return user_repository.get_user_credits(current_user.id) diff --git a/backend/modules/user/repository/users.py b/backend/modules/user/repository/users.py index 9c6ffaa92..cdd181909 100644 --- a/backend/modules/user/repository/users.py +++ b/backend/modules/user/repository/users.py @@ -1,6 +1,8 @@ +import time from models.settings import get_supabase_client from modules.user.entity.user_identity import UserIdentity from modules.user.repository.users_interface import UsersInterface +from modules.user.service import user_usage class Users(UsersInterface): @@ -73,3 +75,11 @@ class Users(UsersInterface): "get_user_email_by_user_id", {"user_id": str(user_id)} ).execute() return response.data[0]["email"] + + def get_user_credits(self, user_id): + user_usage_instance = user_usage.UserUsage(id=user_id) + + user_monthly_usage = user_usage_instance.get_user_monthly_usage(time.strftime("%Y%m%d")) + monthly_chat_credit = self.db.from_("user_settings").select("monthly_chat_credit").filter("user_id", "eq", str(user_id)).execute().data[0]["monthly_chat_credit"] + + return monthly_chat_credit - user_monthly_usage diff --git a/backend/modules/user/repository/users_interface.py b/backend/modules/user/repository/users_interface.py index 69506e33c..a188b455b 100644 --- a/backend/modules/user/repository/users_interface.py +++ b/backend/modules/user/repository/users_interface.py @@ -44,3 +44,10 @@ class UsersInterface(ABC): Get the user email by user id """ pass + + @abstractmethod + def get_user_credits(self, user_id: UUID) -> int: + """ + Get user remaining credits + """ + pass diff --git a/backend/modules/user/service/user_usage.py b/backend/modules/user/service/user_usage.py index cf7834ad9..dc73df750 100644 --- a/backend/modules/user/service/user_usage.py +++ b/backend/modules/user/service/user_usage.py @@ -54,7 +54,7 @@ class UserUsage(UserIdentity): def get_user_monthly_usage(self, date): """ - Fetch the user daily usage from the database + Fetch the user monthly usage from the database """ posthog = PostHogSettings() request = self.supabase_db.get_user_requests_count_for_month(self.id, date) diff --git a/frontend/app/chat/[chatId]/hooks/useChat.ts b/frontend/app/chat/[chatId]/hooks/useChat.ts index 2d846f460..5b786542b 100644 --- a/frontend/app/chat/[chatId]/hooks/useChat.ts +++ b/frontend/app/chat/[chatId]/hooks/useChat.ts @@ -7,9 +7,11 @@ import { useTranslation } from "react-i18next"; import { CHATS_DATA_KEY } from "@/lib/api/chat/config"; import { useChatApi } from "@/lib/api/chat/useChatApi"; +import { useUserApi } from "@/lib/api/user/useUserApi"; import { useChatContext } from "@/lib/context"; import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext"; import { useSearchModalContext } from "@/lib/context/SearchModalProvider/hooks/useSearchModalContext"; +import { useUserSettingsContext } from "@/lib/context/UserSettingsProvider/hooks/useUserSettingsContext"; import { getChatNameFromQuestion } from "@/lib/helpers/getChatNameFromQuestion"; import { useToast } from "@/lib/hooks"; import { useOnboarding } from "@/lib/hooks/useOnboarding"; @@ -42,6 +44,8 @@ export const useChat = () => { chatConfig: { model, maxTokens, temperature }, } = useLocalStorageChatConfig(); const { isVisible } = useSearchModalContext(); + const { getUserCredits } = useUserApi(); + const { setRemainingCredits } = useUserSettingsContext(); const { addStreamQuestion } = useQuestion(); const { t } = useTranslation(["chat"]); @@ -95,6 +99,10 @@ export const useChat = () => { callback?.(); await addStreamQuestion(currentChatId, chatQuestion); + void (async () => { + const res = await getUserCredits(); + setRemainingCredits(res); + })(); } catch (error) { console.error({ error }); diff --git a/frontend/app/search/page.module.scss b/frontend/app/search/page.module.scss index a33ea829f..c47212eac 100644 --- a/frontend/app/search/page.module.scss +++ b/frontend/app/search/page.module.scss @@ -82,6 +82,22 @@ top: 0; left: 0; + .main_message_wrapper { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + .main_message { + display: flex; + flex-direction: column; + + .bolder { + font-weight: bold; + } + } + } + .first_brain_button { position: absolute; right: Spacings.$spacing07; diff --git a/frontend/app/search/page.tsx b/frontend/app/search/page.tsx index dd6c74ad1..d4ee1c025 100644 --- a/frontend/app/search/page.tsx +++ b/frontend/app/search/page.tsx @@ -86,12 +86,22 @@ const Search = (): JSX.Element => { !userIdentityData?.onboarded && !!isUserDataFetched && (