Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added image limitations and language support #210

Merged
merged 13 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions src/client/CookingAppReact/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/client/CookingAppReact/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"framer-motion": "^11.3.21",
"i18next": "^23.14.0",
"jwt-decode": "^4.0.0",
"lottie-react": "^2.4.0",
"lottie-web": "^5.12.2",
Expand All @@ -27,6 +28,7 @@
"react-apexcharts": "^1.4.1",
"react-dom": "^18.3.1",
"react-hot-toast": "^2.4.1",
"react-i18next": "^15.0.1",
"react-icons": "^5.2.1",
"react-redux": "^9.1.2",
"react-router-dom": "^6.25.1",
Expand Down
1 change: 1 addition & 0 deletions src/client/CookingAppReact/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "./index.css";
import "./i18n/config.js";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import SignOutButton from "../src/components/auth/SignOutButton";
import ChatLayout from "./pages/layout/ChatLayout";
Expand Down
30 changes: 19 additions & 11 deletions src/client/CookingAppReact/src/components/chat/BotResponse.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@ import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { useEffect } from "react";
import { uiActions } from "@/store/uiSlice";
import { useTranslation } from "react-i18next";
export default function BotResponse({ message }) {
const language = useSelector((state) => state.ui.lang);
const limitations = useSelector((state) => state.user.role.limitations);
const { i18n, t } = useTranslation();
const role = useSelector((state) => state.user.role.type);
const navigate = useNavigate();
const { save, isError, isPending, error, isSuccess } = useSaveRecipe();

async function handleClick() {
const token = await getToken();
save({ token, request: message.content });
if (!isPending) {
save({ token, request: message.content });
}
}
function handleFreeUser() {
navigate("/subscription");
Expand All @@ -33,9 +39,9 @@ export default function BotResponse({ message }) {
{message.content}
</p>
</div>
{message.type === "Recipe" && role !== "Free" && (
{message.type === "Recipe" && limitations.recipeGeneration > 0 && (
<div className="w-full flex justify-center content-center items-center my-5">
<div
<button
className={`w-fit flex flex-row border border-primaryBorder px-4 py-2 rounded-full bg-primary font-semibold cursor-pointer
${
isPending
Expand All @@ -48,18 +54,20 @@ export default function BotResponse({ message }) {
<SparklesIcon className="size-6 opacity-70 mr-2 text-primaryText" />
{isPending ? (
<span className="text-primaryText">
Generating Meal
<span className="dot-1">.</span>
<span className="dot-2">.</span>
<span className="dot-3">.</span>
{t("GeneratingMeal")}
<span className="dot-1 text-primaryText">.</span>
<span className="dot-2 text-primaryText">.</span>
<span className="dot-3 text-primaryText">.</span>
</span>
) : (
"Generate Meal"
`${t("GenerateMeal")}`
)}
</div>
</button>
</div>
)}
{message.type === "Recipe" && role === "Free" && (
{message.type === "Recipe" &&
role === "Free" &&
limitations.recipeGeneration <= 0 && (
<div className="w-full flex justify-center content-center items-center my-5">
<div
className={`w-fit flex flex-row border-2 px-4 py-2 rounded-full bg-primary font-semibold cursor-pointer
Expand All @@ -72,7 +80,7 @@ export default function BotResponse({ message }) {
onClick={handleFreeUser}
>
<SparklesIcon className="size-6 opacity-70 mr-2" />
<p className="text-primaryText">Get Premium</p>
<p className="text-primaryText">{t("GetPremium")}</p>
</div>
</div>
)}
Expand Down
89 changes: 51 additions & 38 deletions src/client/CookingAppReact/src/components/chat/ChatInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { uiActions } from "../../store/uiSlice";
import toast from "react-hot-toast";
import { useRef } from "react";
import Tooltip from "../ui/tooltip";
import { useTranslation } from "react-i18next";

export default function ChatInput() {
const input = useSelector((state) => state.ui.input);
Expand All @@ -22,6 +23,8 @@ export default function ChatInput() {
const dispatch = useDispatch();
const [base64Image, setBase64Image] = useState(null);
const [maxChars] = useState(200);
const { t } = useTranslation();

useEffect(() => {
if (role.limitations.chatGeneration === 10 && !isInitial) {
toast(
Expand Down Expand Up @@ -75,11 +78,16 @@ export default function ChatInput() {
const file = event.target.files[0];

if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setBase64Image(reader.result);
};
reader.readAsDataURL(file);
console.log(file);
if (file.size > 2000000) {
toast.error("Maximum image size exceeded");
} else {
const reader = new FileReader();
reader.onloadend = () => {
setBase64Image(reader.result);
};
reader.readAsDataURL(file);
}
}
}
useEffect(() => {
Expand Down Expand Up @@ -109,54 +117,59 @@ export default function ChatInput() {

return (
<section className="flex flex-col items-center justify-center mb-5 w-full gap-1 ">
<ul className={`flex
${isOpenRecipes || isOpenSideBar ? "w-4/5 md:w-4/5 lg:w-3/5 xl:w-3/5" : "w-4/5 md:w-3/5 xl:w-2/5"}
items-center secondary rounded-full gap-2 py-2 px-4 bg-active text-primaryText`}>

<Tooltip tooltipText="Attach Image">
<li>
<input
type="file"
hidden
accept="image/*"
ref={fileAttacher}
onChange={(event) => handleImageAttachment(event)}
/>

<PaperClipIcon
className="size-6 cursor-pointer"
onClick={handleClick}
/>
</li>
<ul
className={`flex
${
isOpenRecipes || isOpenSideBar
? "w-4/5 md:w-4/5 lg:w-3/5 xl:w-3/5"
: "w-4/5 md:w-3/5 xl:w-2/5"
}
items-center secondary rounded-full gap-2 py-2 px-4 bg-active text-primaryText`}
>
<Tooltip tooltipText="Attach Image">
<li>
<input
type="file"
hidden
accept="image/*"
ref={fileAttacher}
onChange={(event) => handleImageAttachment(event)}
/>

<PaperClipIcon
className="size-6 cursor-pointer"
onClick={handleClick}
/>
</li>
</Tooltip>
<li className="w-full">
<input
type="text"
value={input}
placeholder="What do you want to cook today?"
placeholder={t("WhatToCook")}
onKeyDown={handleChange}
onChange={handleChange}
maxLength={maxChars}
className="w-full outline-none bg-active text-primaryText"
/>
</li>
<p className="text-sm text-right text-gray-500">
{maxChars - input.length}/200
<p className="text-sm text-right text-primaryText">
{maxChars - input.length}/200
</p>
<Tooltip tooltipText="Send">
<li>
<PaperAirplaneIcon
className={`size-10 rounded-xl p-2 duration-200 ${
input.length > 0 ? "bg-orange-300" : ""
} cursor-pointer`}
onClick={handleSubmission}
/>
</li>

<Tooltip tooltipText="Send">
<li>
<PaperAirplaneIcon
className={`size-10 rounded-xl p-2 duration-200 ${
input.length > 0 ? "bg-orange-300" : ""
} cursor-pointer`}
onClick={handleSubmission}
/>
</li>
</Tooltip>
</ul>
<p className="hidden md:inline text-sm opacity-80 text-primaryText">
Meal Master may occasionally make mistakes.
{t("chatwarn")}
</p>
</section>
);
Expand Down
Loading
Loading