complete renaming functions, abstracts more svg, sets title to current convo title, adds a try again feature to errors

This commit is contained in:
Daniel Avila 2023-02-11 10:22:15 -05:00
parent 592b7629aa
commit 5af5a97d8f
24 changed files with 512 additions and 82 deletions

View file

@ -0,0 +1,108 @@
import React from 'react';
import RenameButton from './RenameButton';
import DeleteButton from './DeleteButton';
import { useSelector, useDispatch } from 'react-redux';
import { setConversation } from '~/store/convoSlice';
import { setMessages } from '~/store/messageSlice';
import { setText } from '~/store/textSlice';
import manualSWR from '~/utils/fetchers';
{
/* <div class="flex py-3 px-3 items-center gap-3 relative rounded-md cursor-pointer hover:pr-14 break-all pr-14 bg-gray-800 hover:bg-gray-800"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 flex-shrink-0" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg><input type="text" class="text-sm border-none bg-transparent p-0 m-0 w-full mr-0" value="titleeeeeeeeeeeeeeeee"><div class="absolute flex right-1 z-10 text-gray-300 visible"><button class="p-1 hover:text-white"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><polyline points="20 6 9 17 4 12"></polyline></svg></button><button class="p-1 hover:text-white"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button></div></div> */
}
export default function Conversation({ id, parentMessageId, title = 'New conversation' }) {
const dispatch = useDispatch();
const { conversationId } = useSelector((state) => state.convo);
const { trigger, isMutating } = manualSWR(`http://localhost:3050/messages/${id}`, 'get');
const clickHandler = async () => {
if (conversationId === id) {
return;
}
dispatch(setConversation({ error: false, conversationId: id, parentMessageId }));
const data = await trigger();
dispatch(setMessages(data));
dispatch(setText(''));
};
const aProps = {
className:
'animate-flash group relative flex cursor-pointer items-center gap-3 break-all rounded-md bg-gray-800 py-3 px-3 pr-14 hover:bg-gray-800'
};
if (conversationId !== id) {
aProps.className =
'group relative flex cursor-pointer items-center gap-3 break-all rounded-md py-3 px-3 hover:bg-[#2A2B32] hover:pr-4';
}
return (
<div class="relative flex cursor-pointer items-center gap-3 break-all rounded-md bg-gray-800 py-3 px-3 pr-14 hover:bg-gray-800 hover:pr-14">
<svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-4 w-4 flex-shrink-0"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
<input
type="text"
class="m-0 mr-0 w-full border-none bg-transparent p-0 text-sm"
value="titleeeeeeeeeeeeeeeee"
/>
<div class="visible absolute right-1 z-10 flex text-gray-300">
<button class="p-1 hover:text-white">
<svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-4 w-4"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</button>
<button class="p-1 hover:text-white">
<svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="h-4 w-4"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="18"
y1="6"
x2="6"
y2="18"
></line>
<line
x1="6"
y1="6"
x2="18"
y2="18"
></line>
</svg>
</button>
</div>
</div>
);
}

View file

@ -1,4 +1,4 @@
import React from 'react';
import React, { useState, useRef } from 'react';
import RenameButton from './RenameButton';
import DeleteButton from './DeleteButton';
import { useSelector, useDispatch } from 'react-redux';
@ -6,23 +6,56 @@ import { setConversation } from '~/store/convoSlice';
import { setMessages } from '~/store/messageSlice';
import { setText } from '~/store/textSlice';
import manualSWR from '~/utils/fetchers';
import ConvoIcon from '../svg/ConvoIcon';
export default function Conversation({ id, parentMessageId, title = 'New conversation' }) {
const [renaming, setRenaming] = useState(false);
const [titleInput, setTitleInput] = useState(title);
const inputRef = useRef(null);
const dispatch = useDispatch();
const { conversationId } = useSelector((state) => state.convo);
const { trigger, isMutating } = manualSWR(`http://localhost:3050/messages/${id}`, 'get');
const rename = manualSWR(`http://localhost:3050/update_convo`, 'post');
const clickHandler = async () => {
if (conversationId === id) {
return;
}
dispatch(setConversation({ error: false, conversationId: id, parentMessageId }));
dispatch(setConversation({ title, error: false, conversationId: id, parentMessageId }));
const data = await trigger();
dispatch(setMessages(data));
dispatch(setText(''));
};
const renameHandler = (e) => {
e.preventDefault();
setRenaming(true);
setTimeout(() => {
inputRef.current.focus();
}, 25);
};
const cancelHandler = (e) => {
e.preventDefault();
setRenaming(false);
};
const onRename = (e) => {
e.preventDefault();
setRenaming(false);
if (titleInput === title) {
return;
}
rename.trigger({ conversationId, title: titleInput });
};
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
onRename(e);
}
};
const aProps = {
className:
'animate-flash group relative flex cursor-pointer items-center gap-3 break-all rounded-md bg-gray-800 py-3 px-3 pr-14 hover:bg-gray-800'
@ -38,27 +71,35 @@ export default function Conversation({ id, parentMessageId, title = 'New convers
onClick={() => clickHandler()}
{...aProps}
>
<svg
stroke="currentColor"
fill="none"
strokeWidth="2"
viewBox="0 0 24 24"
strokeLinecap="round"
strokeLinejoin="round"
className="h-4 w-4"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
</svg>
<ConvoIcon />
<div className="relative max-h-5 flex-1 overflow-hidden text-ellipsis break-all">
{title}
{renaming === true ? (
<input
ref={inputRef}
type="text"
className="m-0 mr-0 w-full leading-tight border border-blue-500 bg-transparent p-0 text-sm outline-none"
value={titleInput}
onChange={(e) => setTitleInput(e.target.value)}
onBlur={onRename}
onKeyPress={handleKeyPress}
/>
) : (
title
)}
</div>
{conversationId === id ? (
<div className="visible absolute right-1 z-10 flex text-gray-300">
<RenameButton conversationId={id} />
<DeleteButton conversationId={id} />
<RenameButton
conversationId={id}
renaming={renaming}
renameHandler={renameHandler}
onRename={onRename}
/>
<DeleteButton
conversationId={id}
renaming={renaming}
cancelHandler={cancelHandler}
/>
</div>
) : (
<div className="absolute inset-y-0 right-0 z-10 w-8 bg-gradient-to-l from-gray-900 group-hover:from-[#2A2B32]" />

View file

@ -1,11 +1,12 @@
import React from 'react';
import TrashIcon from '../svg/TrashIcon';
import CrossIcon from '../svg/CrossIcon';
import manualSWR from '~/utils/fetchers';
import { useDispatch } from 'react-redux';
import { setConversation } from '~/store/convoSlice';
import { setMessages } from '~/store/messageSlice';
export default function DeleteButton({ conversationId }) {
export default function DeleteButton({ conversationId, renaming, cancelHandler }) {
const dispatch = useDispatch();
const { trigger, isMutating } = manualSWR(
'http://localhost:3050/clear_convos',
@ -17,13 +18,14 @@ export default function DeleteButton({ conversationId }) {
);
const clickHandler = () => trigger({ conversationId });
const handler = renaming ? cancelHandler : clickHandler;
return (
<button
className="p-1 hover:text-white"
onClick={clickHandler}
onClick={handler}
>
<TrashIcon />
{ renaming ? <CrossIcon/> : <TrashIcon />}
</button>
);
}

View file

@ -1,23 +1,13 @@
import React from 'react';
import RenameIcon from '../svg/RenameIcon';
import CheckMark from '../svg/CheckMark';
export default function RenameButton({ onClick, renaming, renameHandler, onRename }) {
const handler = renaming ? onRename : renameHandler;
export default function RenameButton({ onClick, disabled }) {
return (
<button className="p-1 hover:text-white">
<svg
stroke="currentColor"
fill="none"
strokeWidth="2"
viewBox="0 0 24 24"
strokeLinecap="round"
strokeLinejoin="round"
className="h-4 w-4"
height="1em"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M12 20h9" />
<path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" />
</svg>
<button className="p-1 hover:text-white" onClick={handler}>
{renaming ? <CheckMark /> : <RenameIcon />}
</button>
);
}