mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-03 06:12:53 +02:00
feat: show chat history always
This commit is contained in:
@@ -30,10 +30,9 @@ import {
|
||||
type MessagePartRenderer,
|
||||
} from '../../lib/render-chat-message';
|
||||
import { RoadmapRecommendations } from '../RoadmapAIChat/RoadmapRecommendations';
|
||||
import type { RoadmapAIChatHistoryType } from '../RoadmapAIChat/RoadmapAIChat';
|
||||
import type { RoadmapAIChatHistoryType } from '../../hooks/use-roadmap-ai-chat';
|
||||
import { AIChatCourse } from './AIChatCouse';
|
||||
import { showLoginPopup } from '../../lib/popup';
|
||||
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';
|
||||
import { readChatStream } from '../../lib/chat';
|
||||
import { chatHistoryOptions } from '../../queries/chat-history';
|
||||
import { cn } from '../../lib/classname';
|
||||
@@ -51,6 +50,7 @@ type AIChatProps = {
|
||||
messages?: RoadmapAIChatHistoryType[];
|
||||
chatHistoryId?: string;
|
||||
setChatHistoryId?: (chatHistoryId: string) => void;
|
||||
onUpgrade?: () => void;
|
||||
};
|
||||
|
||||
export function AIChat(props: AIChatProps) {
|
||||
@@ -58,6 +58,7 @@ export function AIChat(props: AIChatProps) {
|
||||
messages: defaultMessages,
|
||||
chatHistoryId: defaultChatHistoryId,
|
||||
setChatHistoryId: setDefaultChatHistoryId,
|
||||
onUpgrade,
|
||||
} = props;
|
||||
|
||||
const toast = useToast();
|
||||
@@ -70,7 +71,6 @@ export function AIChat(props: AIChatProps) {
|
||||
RoadmapAIChatHistoryType[]
|
||||
>(defaultMessages ?? []);
|
||||
|
||||
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
||||
const [isPersonalizedResponseFormOpen, setIsPersonalizedResponseFormOpen] =
|
||||
useState(false);
|
||||
const [isUploadResumeModalOpen, setIsUploadResumeModalOpen] = useState(false);
|
||||
@@ -128,7 +128,7 @@ export function AIChat(props: AIChatProps) {
|
||||
|
||||
if (isLimitExceeded) {
|
||||
if (!isPaidUser) {
|
||||
setShowUpgradeModal(true);
|
||||
onUpgrade?.();
|
||||
}
|
||||
|
||||
toast.error('Limit reached for today. Please wait until tomorrow.');
|
||||
@@ -343,7 +343,7 @@ export function AIChat(props: AIChatProps) {
|
||||
(index: number) => {
|
||||
if (isLimitExceeded) {
|
||||
if (!isPaidUser) {
|
||||
setShowUpgradeModal(true);
|
||||
onUpgrade?.();
|
||||
}
|
||||
|
||||
toast.error('Limit reached for today. Please wait until tomorrow.');
|
||||
@@ -430,10 +430,6 @@ export function AIChat(props: AIChatProps) {
|
||||
/>
|
||||
)}
|
||||
|
||||
{showUpgradeModal && (
|
||||
<UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />
|
||||
)}
|
||||
|
||||
<div
|
||||
className="pointer-events-none absolute right-0 bottom-0 left-0 mx-auto w-full max-w-3xl px-4"
|
||||
ref={chatContainerRef}
|
||||
@@ -447,7 +443,7 @@ export function AIChat(props: AIChatProps) {
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowUpgradeModal(true)}
|
||||
onClick={() => onUpgrade?.()}
|
||||
className="shrink-0 cursor-pointer rounded-md bg-yellow-200 px-2 py-1 text-xs font-medium text-yellow-800 hover:bg-yellow-200"
|
||||
>
|
||||
Upgrade to Pro
|
||||
@@ -541,7 +537,7 @@ export function AIChat(props: AIChatProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setShowUpgradeModal(true);
|
||||
onUpgrade?.();
|
||||
}}
|
||||
className="rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300"
|
||||
>
|
||||
|
@@ -9,6 +9,7 @@ import { ListChatHistory } from './ListChatHistory';
|
||||
import { billingDetailsOptions } from '../../queries/billing';
|
||||
import { ChatHistoryError } from './ChatHistoryError';
|
||||
import { useClientMount } from '../../hooks/use-client-mount';
|
||||
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';
|
||||
|
||||
type AIChatHistoryProps = {
|
||||
chatHistoryId?: string;
|
||||
@@ -19,6 +20,7 @@ export function AIChatHistory(props: AIChatHistoryProps) {
|
||||
|
||||
const isClientMounted = useClientMount();
|
||||
const [keyTrigger, setKeyTrigger] = useState(0);
|
||||
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
||||
const [isChatHistoryLoading, setIsChatHistoryLoading] = useState(true);
|
||||
const [chatHistoryId, setChatHistoryId] = useState<string | undefined>(
|
||||
defaultChatHistoryId || undefined,
|
||||
@@ -116,13 +118,15 @@ export function AIChatHistory(props: AIChatHistoryProps) {
|
||||
return (
|
||||
<AIChatLayout>
|
||||
<div className="relative flex grow">
|
||||
{isPaidUser && (
|
||||
<ListChatHistory
|
||||
activeChatHistoryId={chatHistoryId}
|
||||
onChatHistoryClick={handleChatHistoryClick}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
)}
|
||||
<ListChatHistory
|
||||
activeChatHistoryId={chatHistoryId}
|
||||
onChatHistoryClick={handleChatHistoryClick}
|
||||
onDelete={handleDelete}
|
||||
isPaidUser={isPaidUser}
|
||||
onUpgrade={() => {
|
||||
setShowUpgradeModal(true);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="relative flex grow">
|
||||
{showLoader && (
|
||||
@@ -151,10 +155,17 @@ export function AIChatHistory(props: AIChatHistoryProps) {
|
||||
},
|
||||
});
|
||||
}}
|
||||
onUpgrade={() => {
|
||||
setShowUpgradeModal(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showUpgradeModal && (
|
||||
<UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />
|
||||
)}
|
||||
</AIChatLayout>
|
||||
);
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ import { queryClient } from '../../stores/query-client';
|
||||
import { ChatHistoryItem } from './ChatHistoryItem';
|
||||
import {
|
||||
Loader2Icon,
|
||||
LockIcon,
|
||||
PanelLeftCloseIcon,
|
||||
PanelLeftIcon,
|
||||
PlusIcon,
|
||||
@@ -25,10 +26,18 @@ type ListChatHistoryProps = {
|
||||
activeChatHistoryId?: string;
|
||||
onChatHistoryClick: (chatHistoryId: string | null) => void;
|
||||
onDelete?: (chatHistoryId: string) => void;
|
||||
isPaidUser?: boolean;
|
||||
onUpgrade?: () => void;
|
||||
};
|
||||
|
||||
export function ListChatHistory(props: ListChatHistoryProps) {
|
||||
const { activeChatHistoryId, onChatHistoryClick, onDelete } = props;
|
||||
const {
|
||||
activeChatHistoryId,
|
||||
onChatHistoryClick,
|
||||
onDelete,
|
||||
isPaidUser,
|
||||
onUpgrade,
|
||||
} = props;
|
||||
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
@@ -122,14 +131,49 @@ export function ListChatHistory(props: ListChatHistoryProps) {
|
||||
(group) => group.histories.length === 0,
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex w-[255px] shrink-0 flex-col justify-start border-r border-gray-200 bg-white p-2',
|
||||
'max-md:absolute max-md:inset-0 max-md:z-20 max-md:w-full',
|
||||
!isOpen && 'hidden',
|
||||
)}
|
||||
const classNames = cn(
|
||||
'flex w-[255px] shrink-0 flex-col justify-start border-r border-gray-200 bg-white p-2',
|
||||
'max-md:absolute max-md:inset-0 max-md:z-20 max-md:w-full',
|
||||
!isOpen && 'hidden',
|
||||
);
|
||||
|
||||
const closeButton = (
|
||||
<button
|
||||
className="flex size-8 items-center justify-center rounded-lg p-1 text-gray-500 hover:bg-gray-100 hover:text-black"
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
}}
|
||||
>
|
||||
<PanelLeftCloseIcon className="h-4.5 w-4.5" />
|
||||
</button>
|
||||
);
|
||||
|
||||
if (!isPaidUser) {
|
||||
return (
|
||||
<div className={cn(classNames, 'relative')}>
|
||||
<div className="absolute top-2 right-2">{closeButton}</div>
|
||||
|
||||
<div className="flex grow flex-col items-center justify-center">
|
||||
<LockIcon className="size-8 text-gray-500" />
|
||||
<p className="mt-4 text-center text-sm text-balance text-gray-500">
|
||||
Upgrade to Pro to keep your chat history.
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
className="mt-2 shrink-0 cursor-pointer rounded-md bg-yellow-200 px-2.5 py-1.5 text-sm font-medium text-yellow-800 hover:bg-yellow-200"
|
||||
onClick={() => {
|
||||
onUpgrade?.();
|
||||
}}
|
||||
>
|
||||
Upgrade to Pro
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames}>
|
||||
{isLoading && <ListChatHistorySkeleton />}
|
||||
{!isLoading && isError && <ChatHistoryError error={error} />}
|
||||
|
||||
@@ -138,18 +182,11 @@ export function ListChatHistory(props: ListChatHistoryProps) {
|
||||
<div>
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<h1 className="font-medium text-gray-900">Chat History</h1>
|
||||
<button
|
||||
className="flex size-8 items-center justify-center rounded-lg p-1 hover:bg-gray-100"
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
}}
|
||||
>
|
||||
<PanelLeftCloseIcon className="h-4.5 w-4.5" />
|
||||
</button>
|
||||
{closeButton}
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="flex w-full items-center hover:opacity-80 justify-center gap-2 rounded-lg bg-black p-2 text-sm text-white"
|
||||
className="flex w-full items-center justify-center gap-2 rounded-lg bg-black p-2 text-sm text-white hover:opacity-80"
|
||||
onClick={() => {
|
||||
if (isMobile) {
|
||||
setIsOpen(false);
|
||||
|
Reference in New Issue
Block a user