Skip to content

Commit

Permalink
Merge pull request #22 from jamakase/feature/front-basement
Browse files Browse the repository at this point in the history
Feature/front basement
  • Loading branch information
FanisNgv authored Sep 8, 2024
2 parents e001138 + 63768d8 commit df409ba
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 65 deletions.
15 changes: 13 additions & 2 deletions frontend/src/app/api.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { API_URL } from "../domain/config";

export const api = {
async createConversation() {
async createConversation(userId: string) {
const response = await fetch(`${API_URL}/conversation/create`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ user_id: userId }),
});
return response.json();
},
Expand All @@ -14,7 +18,7 @@ export const api = {
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ conversation_id: conversationId, message }),
body: JSON.stringify({ conversation_id: conversationId, message:message }),
});
return response.json();
},
Expand All @@ -25,4 +29,11 @@ export const api = {
});
return response.json();
},

async getUserConversations(userId: string) {
const response = await fetch(`${API_URL}/conversation/user/${userId}`, {
method: 'GET',
});
return response.json();
},
};
8 changes: 5 additions & 3 deletions frontend/src/app/components/MessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type MessageListProps = {

export default function MessageList({ messages }: MessageListProps) {
return (
<div className="flex-1 p-4 overflow-y-auto bg-gray-100">
<div className="flex-1 p-4 overflow-y-auto bg-white">
<AnimatePresence>
{messages.map((msg) => (
<motion.div
Expand All @@ -21,9 +21,11 @@ export default function MessageList({ messages }: MessageListProps) {
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}
className={`mb-4 ${msg.sender === 'user' ? 'text-right' : 'text-left'}`}
className={`mb-4 ${msg.sender === 'user' ? 'flex justify-end' : ''}`}
>
<div className={`inline-block p-2 rounded-lg ${msg.sender === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-300 text-black'}`}>
<div className={`inline-block p-2 rounded-lg max-w-[70%] break-words ${
msg.sender === 'user' ? 'bg-[#9400FF] text-white text-left' : 'bg-gray-300 text-black text-justify'
}`}>
{msg.text}
</div>
</motion.div>
Expand Down
112 changes: 85 additions & 27 deletions frontend/src/app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useRef } from 'react';
import Link from 'next/link';
import { motion, AnimatePresence } from 'framer-motion';

type Conversation = {
id: number;
Expand All @@ -20,41 +21,98 @@ export default function Sidebar({ conversations, currentConversationId, onConver
return (
<aside
ref={menuRef}
className="w-64 h-screen bg-black flex flex-col overflow-hidden"
className="w-64 h-screen bg-[#17153B] flex flex-col overflow-hidden"
>
<h1 className="text-4xl font-bold mb-4 bg-[#9400FF] text-center">AFANA</h1>

<div className="p-4">
<h2 className="text-xl font-bold mb-4 text-white">История чатов</h2>
<Link href="/search" className="w-full p-2 mb-4 bg-green-500 rounded-2xl text-white rounded hover:bg-green-600 inline-block text-center">
Перейти к поиску
</Link>
<h2 className="text-2xl font-bold mb-4 text-white text-center">История чатов</h2>

<a
className="group w-full p-2 mb-4 inline-block text-center rounded-full bg-gradient-to-r from-[#27005D] via-[#9400FF] to-[#AED2FF] p-[2px] hover:text-white focus:outline-none active:text-opacity-75 transition-transform active:scale-95" // Добавлен эффект уменьшения при нажатии
href="/search"
>
<span
className="block rounded-full bg-black px-4 py-1 text-sm font-medium group-hover:bg-transparent"
>
<h2 className="text-sm text-white text-center">
Перейти к поиску
</h2>
</span>
</a>

<button
className="group w-full p-2 mb-4 inline-block text-center rounded-full bg-gradient-to-r from-[#070260] via-[#090979] to-[#00d4ff] p-[2px] hover:text-white focus:outline-none active:text-opacity-75 cursor-pointer select-none transition-transform active:scale-95" // Добавлен эффект уменьшения при нажатии
onClick={onAddConversation}
className="w-full p-2 bg-blue-500 text-white rounded-2xl hover:bg-blue-600"
>
Новый чат
</button>

<span
className="block rounded-full bg-black px-4 py-1 text-sm font-medium group-hover:bg-transparent"
>
<h2 className="text-sm text-white text-center">
Новый чат
</h2>
</span>

</button>
</div>
<div className="flex-1 overflow-y-auto px-4 pb-4">
<ul>
{conversations.map((conversation) => (
<li key={conversation.id} className="mb-2 flex justify-between items-center">
<button
className={`flex-grow text-left p-2 hover:bg-gray-700 rounded text-white ${currentConversationId === conversation.id ? 'bg-gray-700' : ''}`}
onClick={() => onConversationChange(conversation.id)}
>
{conversation.name}
</button>
<button
onClick={() => onDeleteConversation(conversation.id)}
className="ml-2 p-1 text-red-500 hover:text-red-700"
<div className="flex-1 overflow-y-auto px-4 pb-4 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:'none'] [scrollbar-width:'none']">
<fieldset className="space-y-4">
<legend className="sr-only">Чаты</legend>
<AnimatePresence mode="popLayout">
{conversations.map((conversation) => (
<motion.div
key={conversation.id}
layout
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{
opacity: { duration: 0.2 },
layout: { duration: 0.4 },
scale: { duration: 0.2 }
}}
>
X
</button>
</li>
))}
</ul>
<label
htmlFor={`chat-${conversation.id}`}
className={`flex text-base cursor-pointer items-center justify-between gap-4 rounded-lg border border-gray-700 p-4 text-sm font-medium shadow-sm hover:border-[#9400FF] ${
currentConversationId === conversation.id
? 'bg-[#9400FF] text-black'
: 'bg-[#2E236C] text-white'
}`}
>
<p className="text-white">{conversation.name}</p>
<button
onClick={(e) => {
e.preventDefault();
onDeleteConversation(conversation.id);
}}
className="text-red-500 hover:text-red-700"
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 -960 960 960"
width="24"
fill="#00d4ff"
className="hover:fill-[#00ABCD]"
>
<path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/>
</svg>
</button>
<input
type="radio"
name="ChatOption"
value={`chat-${conversation.id}`}
id={`chat-${conversation.id}`}
className="sr-only"
checked={currentConversationId === conversation.id}
onChange={() => onConversationChange(conversation.id)}
/>
</label>
</motion.div>
))}
</AnimatePresence>
</fieldset>
</div>
</aside>
);
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,16 @@ body {

.hide-scrollbar::-webkit-scrollbar {
display: none;
}

body, input, button, textarea {
font-family: "Inter", sans-serif;
}

* {
font-family: "Inter", sans-serif;
}

body, input, button, textarea, select {
font-family: "Inter", sans-serif;
}
4 changes: 3 additions & 1 deletion frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { Metadata } from "next";
import { Roboto_Mono } from "next/font/google";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });
const robotoMono = Roboto_Mono({ subsets: ["latin", "cyrillic"], weight: ['400', '700'], display: 'swap' });
const inter = Inter({ subsets: ["latin", "cyrillic"] });

export const metadata: Metadata = {
title: "afana-propdoc",
Expand Down
68 changes: 44 additions & 24 deletions frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"use client";
import { useState, useRef, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import Link from 'next/link';

import { useState, useEffect } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { api } from './api';
import Sidebar from './components/Sidebar';
import MessageList from './components/MessageList';


type Conversation = {
id: number;
name: string;
Expand All @@ -15,38 +14,51 @@ type Conversation = {

export default function Home() {
const [conversations, setConversations] = useState<Conversation[]>([]);
const [currentConversationId, setCurrentConversationId] = useState<number | null>(null);
const [message, setMessage] = useState('');
const [messages, setMessages] = useState<Array<{ id: number; text: string; sender: string }>>([]);
const [currentConversationId, setCurrentConversationId] = useState<number | null>(null);
const [userId, setUserId] = useState<string | null>(null);

useEffect(() => {
const createInitialChat = async () => {
if (conversations.length === 0) {
try {
const initializeUser = async () => {
let storedUserId = localStorage.getItem('userId');

if (!storedUserId) {
storedUserId = uuidv4();
localStorage.setItem('userId', storedUserId);
}

setUserId(storedUserId);

try {
const userConversations = await api.getUserConversations(storedUserId);
if (userConversations.length > 0) {
setConversations(userConversations);
setCurrentConversationId(userConversations[0].id);
setMessages(userConversations[0].messages);
} else {
const newConversation = await handleAddConversation();
setConversations([newConversation]);
setCurrentConversationId(newConversation.id);
} catch (error) {
console.error('Ошибка при создании начального чата:', error);
}
} catch (error) {
console.error('Ошибка при инициализации пользователя:', error);
}
};

createInitialChat();
initializeUser();
}, []);

const handleSendMessage = async () => {
if (!message.trim()) return;

try {
if (currentConversationId === null) {
await handleAddConversation();
}

if (currentConversationId === null) {
throw new Error('Не удалось создать или выбрать чат');
const newConversation = await handleAddConversation();
if (!newConversation) {
throw new Error('Не удалось создать новый чат');
}
}

const newMessage = {
id: messages.length + 1,
text: message,
Expand All @@ -63,11 +75,13 @@ export default function Home() {
);

const response = await api.sendMessage(currentConversationId!, message);

if (!response.task_id) {
throw new Error('Ошибка при отправке сообщения');
}

console.log('Сообщение успешно отправлено, task_id:', response.task_id);
setMessage('');

let botResponse;
do {
Expand All @@ -92,7 +106,6 @@ export default function Home() {
);
}

setMessage('');
} catch (error) {
console.error('Произошла ошибка:', error);
setMessage('');
Expand All @@ -115,10 +128,11 @@ export default function Home() {

const handleAddConversation = async () => {
try {
const response = await api.createConversation();
if (!userId) throw new Error('UserId не определен');
const response = await api.createConversation(userId);
if (response.conversation_id) {
const newConversation = {
id: conversations.length + 1,
id: response.conversation_id,
name: `Чат ${conversations.length + 1}`,
messages: []
};
Expand Down Expand Up @@ -164,22 +178,28 @@ export default function Home() {
<div className="flex-1 flex flex-col h-screen">
<MessageList messages={messages} />

<div className="p-4 bg-white border-t border-gray-200">
<div className="p-4 bg-white">
<div className="flex">
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Введите ваш вопрос"
className="flex-grow p-2 border border-gray-300 rounded-l-2xl focus:outline-none"
className="flex-grow p-2 bg-gray-300 border border-gray-300 rounded-l-2xl focus:outline-none"
style={{ color: 'black' }}
/>
<button
onClick={handleSendMessage}
className="px-4 py-2 bg-blue-500 text-white rounded-r-2xl hover:bg-blue-600 focus:outline-none"

className="group w-auto inline-block text-center rounded-r-2xl
bg-[#2E236C] p-[2px]focus:outline-none cursor-pointer select-none"
>
Отправить
<span className="block rounded-r-2xl bg-[#17153B] px-6 py-3 text-sm font-medium group-hover:bg-transparent">
<h2 className="text-sm text-white">
Отправить
</h2>
</span>
</button>
</div>
</div>
Expand Down
Loading

0 comments on commit df409ba

Please sign in to comment.