message-style frontend

This commit is contained in:
2025-10-10 23:28:41 -04:00
parent c978b1a255
commit 376baccadb
2 changed files with 109 additions and 45 deletions

Binary file not shown.

View File

@@ -4,42 +4,121 @@ import ReactMarkdown from "react-markdown";
import "./App.css"; import "./App.css";
type QuestionAnswer = {
question: string;
answer: string;
};
type QuestionBubbleProps = {
text: string;
};
type AnswerBubbleProps = {
text: string;
loading: string;
};
type QuestionAnswerPairProps = {
question: string;
answer: string;
loading: boolean;
};
const QuestionBubble = ({ text }: QuestionBubbleProps) => {
return <div className="rounded-md bg-stone-200 p-3">🤦: {text}</div>;
};
const AnswerBubble = ({ text, loading }: AnswerBubbleProps) => {
return (
<div className="rounded-md bg-orange-100 p-3">
{loading ? (
<div className="flex flex-col w-full animate-pulse gap-2">
<div className="flex flex-row gap-2 w-full">
<div className="bg-gray-400 w-1/2 p-3 rounded-lg" />
<div className="bg-gray-400 w-1/2 p-3 rounded-lg" />
</div>
<div className="flex flex-row gap-2 w-full">
<div className="bg-gray-400 w-1/3 p-3 rounded-lg" />
<div className="bg-gray-400 w-2/3 p-3 rounded-lg" />
</div>
</div>
) : (
<div className="flex flex-col">
<ReactMarkdown>{"🐈: " + text}</ReactMarkdown>
</div>
)}
</div>
);
};
const QuestionAnswerPair = ({
question,
answer,
loading,
}: QuestionAnswerPairProps) => {
return (
<div className="flex flex-col gap-4">
<QuestionBubble text={question} />
<AnswerBubble text={answer} loading={loading} />
</div>
);
};
const App = () => { const App = () => {
const [query, setQuery] = useState<string>(""); const [query, setQuery] = useState<string>("");
const [answer, setAnswer] = useState<string>(""); const [answer, setAnswer] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
const [simbaMode, setSimbaMode] = useState<boolean>(false); const [simbaMode, setSimbaMode] = useState<boolean>(false);
const [questionsAnswers, setQuestionsAnswers] = useState<QuestionAnswer[]>(
[]
);
const simbaAnswers = ["meow.", "hiss...", "purrrrrr", "yowOWROWWowowr"]; const simbaAnswers = ["meow.", "hiss...", "purrrrrr", "yowOWROWWowowr"];
const handleQuestionSubmit = () => { const handleQuestionSubmit = () => {
if (simbaMode) { if (simbaMode) {
console.log("simba mode activated"); console.log("simba mode activated");
setLoading(true);
const randomIndex = Math.floor(Math.random() * simbaAnswers.length); const randomIndex = Math.floor(Math.random() * simbaAnswers.length);
const randomElement = simbaAnswers[randomIndex]; const randomElement = simbaAnswers[randomIndex];
setAnswer(randomElement); setAnswer(randomElement);
setTimeout(() => setLoading(false), 3500); setQuestionsAnswers(
questionsAnswers.concat([
{
question: query,
answer: randomElement,
},
])
);
return; return;
} }
const payload = { query: query }; const payload = { query: query };
setLoading(true);
axios axios
.post("/api/query", payload) .post("/api/query", payload)
.then((result) => setAnswer(result.data.response)) .then((result) =>
.finally(() => setLoading(false)); setQuestionsAnswers(
questionsAnswers.concat([
{ question: query, answer: result.data.response },
])
)
);
}; };
const handleQueryChange = (event) => { const handleQueryChange = (event) => {
setQuery(event.target.value); setQuery(event.target.value);
}; };
return ( return (
<div className="bg-[url('./simba_cute.jpeg')] bg-cover bg-center bg-no-repeat h-screen bg-opacity-20"> <div className="h-screen bg-opacity-20">
<div className="bg-white/85 h-screen"> <div className="bg-white/85 h-screen">
<div className="flex flex-row justify-center py-4"> <div className="flex flex-row justify-center py-4">
<div className="flex flex-col gap-4 min-w-xl max-w-xl"> <div className="flex flex-col gap-4 min-w-xl max-w-xl">
<div className="flex flex-row justify-center gap-2 grow"> <div className="flex flex-row justify-center gap-2 grow">
<h1 className="text-3xl">ask simba!</h1> <h1 className="text-3xl">ask simba!</h1>
</div> </div>
{questionsAnswers.map((qa) => (
<QuestionAnswerPair
question={qa.question}
answer={qa.answer}
/>
))}
<footer className="flex flex-col gap-2 sticky bottom-0">
<div className="flex flex-row justify-between gap-2 grow"> <div className="flex flex-row justify-between gap-2 grow">
<textarea <textarea
type="text" type="text"
@@ -65,22 +144,7 @@ const App = () => {
/> />
<p>simba mode?</p> <p>simba mode?</p>
</div> </div>
{loading ? ( </footer>
<div className="flex flex-col w-full animate-pulse gap-2">
<div className="flex flex-row gap-2 w-full">
<div className="bg-gray-400 w-1/2 p-3 rounded-lg" />
<div className="bg-gray-400 w-1/2 p-3 rounded-lg" />
</div>
<div className="flex flex-row gap-2 w-full">
<div className="bg-gray-400 w-1/3 p-3 rounded-lg" />
<div className="bg-gray-400 w-2/3 p-3 rounded-lg" />
</div>
</div>
) : (
<div className="flex flex-col">
<ReactMarkdown>{answer}</ReactMarkdown>
</div>
)}
</div> </div>
</div> </div>
</div> </div>