diff --git a/src/client/CookingAppReact/src/components/auth/SignOutButton.jsx b/src/client/CookingAppReact/src/components/auth/SignOutButton.jsx
index 5dd8c756..a423475c 100644
--- a/src/client/CookingAppReact/src/components/auth/SignOutButton.jsx
+++ b/src/client/CookingAppReact/src/components/auth/SignOutButton.jsx
@@ -1,11 +1,13 @@
"use client";
import { handleLogout } from "@/msal/msal";
import { FaSignOutAlt } from "react-icons/fa";
+import { useTranslation } from "react-i18next";
import { ArrowRightStartOnRectangleIcon } from "@heroicons/react/24/outline";
// import { useTheme } from "next-themes";
const SignOutButton = () => {
+ const { i18n, t } = useTranslation();
// const { theme } = useTheme();
// const isDarkTheme = theme === 'dark';
@@ -20,7 +22,7 @@ const SignOutButton = () => {
// color={isDarkTheme ? "white" : "black"}
/>
Sign Out
+ className={`text-primaryText`}>{t("SignOut")}
);
};
diff --git a/src/client/CookingAppReact/src/components/chat/BotResponse.jsx b/src/client/CookingAppReact/src/components/chat/BotResponse.jsx
index 539927ce..9a76b540 100644
--- a/src/client/CookingAppReact/src/components/chat/BotResponse.jsx
+++ b/src/client/CookingAppReact/src/components/chat/BotResponse.jsx
@@ -9,22 +9,36 @@ import { useEffect } from "react";
import { uiActions } from "@/store/uiSlice";
import { useTranslation } from "react-i18next";
import { useGeneration } from "@/utils/generationProvider";
+import toast from "react-hot-toast";
+
export default function BotResponse({ message }) {
const language = useSelector((state) => state.ui.lang);
const limitations = useSelector((state) => state.user.role.limitations);
- const { isGenerating, setIsGenerating } = useGeneration();
const { i18n, t } = useTranslation();
const role = useSelector((state) => state.user.role.type);
const navigate = useNavigate();
const { save, isError, isPending, error, isSuccess } = useSaveRecipe();
+ const { isGenerating, setIsGenerating, lastTimestamp, maxDuration } = useGeneration();
async function handleClick() {
+ const timeElapsed = Date.now() - lastTimestamp;
+ const isCooldown = timeElapsed < maxDuration;
const token = await getToken();
- if (!isPending && !isGenerating) {
+
+ if (isGenerating && isCooldown) {
+ const timeRemaining = maxDuration - timeElapsed;
+ const minutes = Math.floor(timeRemaining / 60000);
+ const seconds = Math.floor((timeRemaining % 60000) / 1000);
+ toast.error(`Meal generation cooldown - ${minutes}:${seconds} minutes.`);
+ return;
+ } else if(!isPending && !isGenerating){
setIsGenerating(true);
save({ token, request: message.content });
+ } else{
+ setIsGenerating(false);
}
}
+
function handleFreeUser() {
navigate("/subscription");
}
@@ -50,8 +64,7 @@ export default function BotResponse({ message }) {
isPending
? "border-dance animate-border-dance"
: "hover:scale-105 transition-transform duration-300"
- }
- relative ${isPending && "sparkle"}`}
+ } `}
onClick={handleClick}
>
diff --git a/src/client/CookingAppReact/src/components/chat/Thinking.jsx b/src/client/CookingAppReact/src/components/chat/Thinking.jsx
index 1c36cb55..66318584 100644
--- a/src/client/CookingAppReact/src/components/chat/Thinking.jsx
+++ b/src/client/CookingAppReact/src/components/chat/Thinking.jsx
@@ -20,12 +20,12 @@ const Thinking = () => {
/>
- •
- •
- •
+ •
+ •
+ •
diff --git a/src/client/CookingAppReact/src/components/recipes/MyRecipes.jsx b/src/client/CookingAppReact/src/components/recipes/MyRecipes.jsx
index 640e82fb..ef9f846f 100644
--- a/src/client/CookingAppReact/src/components/recipes/MyRecipes.jsx
+++ b/src/client/CookingAppReact/src/components/recipes/MyRecipes.jsx
@@ -109,7 +109,7 @@ export default function MyRecipes() {
onClick={handleRecipes}
/>
-
{t("MyMeals")}
+ {t("MyMeals")}
{t("LoadMore")}
- .
- .
- .
+ .
+ .
+ .
)}
diff --git a/src/client/CookingAppReact/src/hooks/useSaveRecipe.js b/src/client/CookingAppReact/src/hooks/useSaveRecipe.js
index 0632c2f9..195e5fdf 100644
--- a/src/client/CookingAppReact/src/hooks/useSaveRecipe.js
+++ b/src/client/CookingAppReact/src/hooks/useSaveRecipe.js
@@ -30,19 +30,19 @@ const useSaveRecipe = () => {
mutationFn: createRecipe,
onMutate: () => {
setIsGenerating(true);
- dispatch(userActions.reduceRecipeGeneration());
},
onSuccess: async (response) => {
+ setIsGenerating(false);
+ dispatch(userActions.reduceRecipeGeneration());
dispatch(uiActions.showToast(response));
const token = await getToken();
const decoded = jwtDecode(token);
console.log("trigerring");
getFirstPageRecipes({ token: token, page: 1, userId: decoded.sub });
- setIsGenerating(false);
},
onError: (error) => {
- dispatch(uiActions.setResponseError(error.message));
setIsGenerating(false);
+ dispatch(uiActions.setResponseError(error.message));
},
});
diff --git a/src/client/CookingAppReact/src/i18n/config.js b/src/client/CookingAppReact/src/i18n/config.js
index 1d66a666..4114f6c2 100644
--- a/src/client/CookingAppReact/src/i18n/config.js
+++ b/src/client/CookingAppReact/src/i18n/config.js
@@ -59,7 +59,7 @@ i18n.use(initReactI18next).init({
CopyUserId: "Copy User Id",
Profile: "Profile",
WhatToCook: "What do you want to cook today?",
- LookingForFav: "Looking for your favourite recipe?",
+ LookingForFav: "Looking for your favourite meal?",
AddAllergens: "Add your allergens",
AddDisliked: "Add your disliked foods"
},
diff --git a/src/client/CookingAppReact/src/index.css b/src/client/CookingAppReact/src/index.css
index ba25827a..5ead4b1b 100644
--- a/src/client/CookingAppReact/src/index.css
+++ b/src/client/CookingAppReact/src/index.css
@@ -15,8 +15,8 @@
::-webkit-scrollbar-thumb {
background: linear-gradient(
135deg,
- #a0a0a0,
- #606060
+ #808080,
+ #808080
); /* Gradient thumb for a cool effect */
border-radius: 10px; /* Rounded corners for the thumb */
}
@@ -25,7 +25,7 @@
background: linear-gradient(
135deg,
#808080,
- #404040
+ #808080
); /* Darker gradient on hover */
}
.light {
diff --git a/src/client/CookingAppReact/src/pages/chat/Chat.jsx b/src/client/CookingAppReact/src/pages/chat/Chat.jsx
index 6ea77981..0620d593 100644
--- a/src/client/CookingAppReact/src/pages/chat/Chat.jsx
+++ b/src/client/CookingAppReact/src/pages/chat/Chat.jsx
@@ -53,7 +53,7 @@ export default function Chat() {
return (
*:last-child]:pb-5
+ className={`flex flex-col gap-14 justify-start items-center [&>*:last-child]:pb-1
${
isOpenRecipes || isOpenSideBar
? "w-5/5 md:w-5/5 xl:w-4/5"
diff --git a/src/client/CookingAppReact/src/pages/subscribtion/SubscriptionDetails.jsx b/src/client/CookingAppReact/src/pages/subscribtion/SubscriptionDetails.jsx
index 178169e3..2b626a9a 100644
--- a/src/client/CookingAppReact/src/pages/subscribtion/SubscriptionDetails.jsx
+++ b/src/client/CookingAppReact/src/pages/subscribtion/SubscriptionDetails.jsx
@@ -18,8 +18,8 @@ export default function SubscriptionDetails() {
function formatDateIso(dateString) {
const date = new Date(dateString);
-
- // Adjust for time zone offset
+
+ // Define options for formatting the date
const options = {
year: "numeric",
month: "long",
@@ -27,11 +27,10 @@ export default function SubscriptionDetails() {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
- timeZone: "UTC", // Ensure the date is interpreted as UTC
hour12: true, // Use 12-hour time format
};
-
- // Format date
+
+ // Format the date according to the user's local timezone
return new Intl.DateTimeFormat("en-US", options).format(date);
}
@@ -68,7 +67,7 @@ export default function SubscriptionDetails() {
) : (
-
- {`Your next charge will be on ${data.subscriptions[0].currentPeriodEnd}`}
+ {`Your next charge will be on ${formatDateIso(data.subscriptions[0].currentPeriodEnd)}`}
)}
diff --git a/src/client/CookingAppReact/src/utils/generationProvider.jsx b/src/client/CookingAppReact/src/utils/generationProvider.jsx
index 57e1f824..d8ab5f6e 100644
--- a/src/client/CookingAppReact/src/utils/generationProvider.jsx
+++ b/src/client/CookingAppReact/src/utils/generationProvider.jsx
@@ -1,21 +1,36 @@
import React, { createContext, useContext, useState, useEffect } from "react";
+import toast from "react-hot-toast";
const GenerationContext = createContext();
+const calculateElapsed = (lastTimestamp, maxDuration) => {
+ const now = Date.now();
+ const timeElapsed = now - lastTimestamp;
+ return timeElapsed < maxDuration;
+};
+
export const GenerationProvider = ({ children }) => {
+ const maxDuration = 2 * 60 * 1000; // 2 minutes in milliseconds
+
const [isGenerating, setIsGenerating] = useState(() => {
- // Retrieve the initial state from local storage
const savedState = localStorage.getItem('isGenerating');
- return savedState ? JSON.parse(savedState) : false;
+ const lastTimestamp = JSON.parse(localStorage.getItem('generationTimestamp'));
+ const isElapsed = lastTimestamp ? calculateElapsed(lastTimestamp, maxDuration) : false;
+ return savedState && isElapsed ? JSON.parse(savedState) : false;
});
+ const lastTimestamp = JSON.parse(localStorage.getItem('generationTimestamp')) || null;
+ const isElapsed = lastTimestamp ? calculateElapsed(lastTimestamp, maxDuration) : false;
+
useEffect(() => {
- // Save the state to local storage whenever it changes
localStorage.setItem('isGenerating', JSON.stringify(isGenerating));
+ if (isGenerating) {
+ localStorage.setItem('generationTimestamp', JSON.stringify(Date.now()));
+ }
}, [isGenerating]);
return (
-
+
{children}
);
diff --git a/src/server/CookingApp/Properties/launchSettings.json b/src/server/CookingApp/Properties/launchSettings.json
index 53febc9a..1f9e41a0 100644
--- a/src/server/CookingApp/Properties/launchSettings.json
+++ b/src/server/CookingApp/Properties/launchSettings.json
@@ -8,7 +8,7 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
- "applicationUrl": "http://192.168.100.221:8000"
+ "applicationUrl": "http://192.168.0.103:8000"
},
"https": {
"commandName": "Project",