Files
nirvana/packages/web/components/Conversations/ConversationFullRow.tsx
T

236 lines
7.4 KiB
TypeScript

import Conversation from "@nirvana/common/models/conversation";
import { Avatar, Tooltip } from "antd";
import moment from "moment";
import {
FaCircle,
FaUser,
FaRocket,
FaRegClock,
FaCheck,
FaAngleRight,
FaStream,
FaDotCircle,
} from "react-icons/fa";
import { useRecoilValue } from "recoil";
import {
allRelevantConversationsAtom,
allUsersConversationsAtom,
checkIncomingMessageSelector,
} from "../../recoil/main";
import { MasterAvatarGroupWithUserFetch } from "../UserDetails/MasterAvatarGroup";
import { FaPlay } from "react-icons/fa";
import { ConversationMemberState } from "../../../common/models/conversation";
import { conversationService } from "@nirvana/common/services";
import { useAuth } from "../../contexts/authContext";
import toast from "react-hot-toast";
import { useRouter } from "next/router";
import { Routes } from "@nirvana/common/helpers/routes";
export default function ConversationFullRow(props: {
conversation: Conversation;
handleJoinLive?: (conversationId: string) => Promise<void>;
handleLeaveLive?: (conversationId: string) => Promise<void>;
}) {
const { currUser } = useAuth();
const usersConvosMap = useRecoilValue(allUsersConversationsAtom);
// check if I am outdate on a certain conversation
const isNewIncoming = useRecoilValue(
checkIncomingMessageSelector(props.conversation.id)
);
const handleOrganizeConversation = async (
toState: ConversationMemberState
) => {
try {
// use service to make change in database which will change local data
await conversationService.updateUserConvoRelationship(
currUser!.uid,
props.conversation.id,
toState
);
toast.success("Moved conversation to " + toState);
} catch (error) {
console.error(error);
toast.error("Problem in moving conversation");
}
};
const router = useRouter();
const handleViewConversationDetails = (e) => {
router.push({
pathname: Routes.home,
query: { convoId: props.conversation.id },
});
};
const playLastClip = () => {
if (!props.conversation.cachedAudioClip) {
toast.error("Nothing to play");
return;
}
// todo: add to queue instead of playing here
const audio = new Audio(props.conversation.cachedAudioClip.audioDataUrl);
audio.play();
};
/**
* show actions based on which state it is currently in for this user
*/
const currUserAssoc = usersConvosMap.get(props.conversation.id);
let currConvoMemberState: ConversationMemberState =
ConversationMemberState.default;
if (currUserAssoc) {
if (currUserAssoc.state == ConversationMemberState.later) {
currConvoMemberState = ConversationMemberState.later;
} else if (currUserAssoc.state == ConversationMemberState.done) {
currConvoMemberState = ConversationMemberState.done;
} else if (currUserAssoc.state == ConversationMemberState.priority) {
currConvoMemberState = ConversationMemberState.priority;
}
}
return (
<span
onClick={handleViewConversationDetails}
className={`py-5 px-4 border-t border-t-slate-200 flex flex-row last:border-b-slate-200 last:border-b
hover:bg-slate-50 transition-all items-center group relative hover:cursor-pointer ${
isNewIncoming ? "bg-slate-50" : "text-slate-100"
}`}
>
<FaCircle
className={`mr-2 animate-pulse text-[0.75rem] ${
isNewIncoming ? "text-orange-500" : "text-slate-100"
}`}
/>
<span className="flex flex-row items-center">
<span className="w-[5rem]">
<MasterAvatarGroupWithUserFetch
listOfUserIds={props.conversation.activeMembers}
showCurrUser={false}
/>
</span>
<span
className={`ml-2 ${
isNewIncoming ? "text-slate-500 font-semibold" : "text-slate-400"
}`}
>
{props.conversation.name}
</span>
</span>
<span
className="ml-2 flex flex-row items-center
group-hover:visible invisible text-slate-400"
>
{props.handleJoinLive && (
<Tooltip title={"Join live."}>
<span
onClick={(e) => {
e.stopPropagation();
if (props.handleJoinLive) {
props.handleJoinLive(props.conversation.id);
}
}}
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200"
>
<FaDotCircle className="ml-auto text-lg text-red-500" />
</span>
</Tooltip>
)}
<Tooltip title={"Play last convo chunk."}>
<span
onClick={(e) => {
e.stopPropagation();
playLastClip();
}}
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200"
>
<FaPlay className="ml-auto text-lg text-emerald-500" />
</span>
</Tooltip>
</span>
<span className="text-slate-300 w-[20rem] truncate text-sm">
{props.conversation.tldr}
</span>
<span
className={`ml-auto text-sm group-hover:invisible ${
isNewIncoming ? "text-slate-400 font-semibold" : "text-slate-300"
}`}
>
{moment(props.conversation.lastActivityDate?.toDate()).fromNow()}
</span>
{/* actions */}
<span
className="ml-auto flex flex-row items-center
group-hover:visible invisible absolute right-5 text-slate-400"
>
{currConvoMemberState != ConversationMemberState.default && (
<Tooltip title={"Inbox"}>
<span
onClick={(e) => {
e.stopPropagation();
handleOrganizeConversation(ConversationMemberState.default);
}}
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200"
>
<FaStream className="ml-auto text-lg" />
</span>
</Tooltip>
)}
{currConvoMemberState != ConversationMemberState.later && (
<Tooltip title={"Later"}>
<span
onClick={(e) => {
e.stopPropagation();
handleOrganizeConversation(ConversationMemberState.later);
}}
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200"
>
<FaRegClock className="ml-auto text-lg" />
</span>
</Tooltip>
)}
{currConvoMemberState != ConversationMemberState.priority && (
<Tooltip title={"Priority"}>
<span
onClick={(e) => {
e.stopPropagation();
handleOrganizeConversation(ConversationMemberState.priority);
}}
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200"
>
<FaRocket className="ml-auto text-lg" />
</span>
</Tooltip>
)}
{currConvoMemberState != ConversationMemberState.done && (
<Tooltip title={"Done"}>
<span
onClick={(e) => {
e.stopPropagation();
handleOrganizeConversation(ConversationMemberState.done);
}}
className="p-2 rounded-full hover:cursor-pointer hover:bg-slate-200"
>
<FaCheck className="ml-auto text-lg" />
</span>
</Tooltip>
)}
</span>
</span>
);
}