mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-03 06:12:53 +02:00
Upgrade flow in floating chat
This commit is contained in:
@@ -185,6 +185,7 @@ export function UpgradeAccountModal(props: UpgradeAccountModalProps) {
|
|||||||
bodyClassName="p-4 sm:p-6 bg-white"
|
bodyClassName="p-4 sm:p-6 bg-white"
|
||||||
wrapperClassName="h-auto rounded-xl max-w-3xl w-full min-h-[540px] mx-2 sm:mx-4"
|
wrapperClassName="h-auto rounded-xl max-w-3xl w-full min-h-[540px] mx-2 sm:mx-4"
|
||||||
overlayClassName="items-start md:items-center"
|
overlayClassName="items-start md:items-center"
|
||||||
|
hasCloseButton={true}
|
||||||
>
|
>
|
||||||
<div onClick={(e) => e.stopPropagation()}>
|
<div onClick={(e) => e.stopPropagation()}>
|
||||||
{errorContent}
|
{errorContent}
|
||||||
|
@@ -22,14 +22,15 @@ import {
|
|||||||
import { cn } from '../../lib/classname';
|
import { cn } from '../../lib/classname';
|
||||||
import { lockBodyScroll } from '../../lib/dom';
|
import { lockBodyScroll } from '../../lib/dom';
|
||||||
import { slugify } from '../../lib/slugger';
|
import { slugify } from '../../lib/slugger';
|
||||||
|
import { getAiCourseLimitOptions } from '../../queries/ai-course';
|
||||||
|
import { billingDetailsOptions } from '../../queries/billing';
|
||||||
import { roadmapJSONOptions } from '../../queries/roadmap';
|
import { roadmapJSONOptions } from '../../queries/roadmap';
|
||||||
import { roadmapQuestionsOptions } from '../../queries/roadmap-questions';
|
import { roadmapQuestionsOptions } from '../../queries/roadmap-questions';
|
||||||
import { queryClient } from '../../stores/query-client';
|
import { queryClient } from '../../stores/query-client';
|
||||||
|
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';
|
||||||
import { RoadmapAIChatCard } from '../RoadmapAIChat/RoadmapAIChatCard';
|
import { RoadmapAIChatCard } from '../RoadmapAIChat/RoadmapAIChatCard';
|
||||||
import { UpdatePersonaModal } from '../UserPersona/UpdatePersonaModal';
|
|
||||||
import { CLOSE_TOPIC_DETAIL_EVENT } from '../TopicDetail/TopicDetail';
|
import { CLOSE_TOPIC_DETAIL_EVENT } from '../TopicDetail/TopicDetail';
|
||||||
import { billingDetailsOptions } from '../../queries/billing';
|
import { UpdatePersonaModal } from '../UserPersona/UpdatePersonaModal';
|
||||||
import { getAiCourseLimitOptions } from '../../queries/ai-course';
|
|
||||||
|
|
||||||
type ChatHeaderButtonProps = {
|
type ChatHeaderButtonProps = {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
@@ -156,6 +157,7 @@ export function RoadmapFloatingChat(props: RoadmapChatProps) {
|
|||||||
const [inputValue, setInputValue] = useState('');
|
const [inputValue, setInputValue] = useState('');
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const [isPersonalizeOpen, setIsPersonalizeOpen] = useState(false);
|
const [isPersonalizeOpen, setIsPersonalizeOpen] = useState(false);
|
||||||
|
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
||||||
|
|
||||||
// Fetch questions from API
|
// Fetch questions from API
|
||||||
const { data: questionsData } = useQuery(
|
const { data: questionsData } = useQuery(
|
||||||
@@ -292,6 +294,14 @@ export function RoadmapFloatingChat(props: RoadmapChatProps) {
|
|||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showUpgradeModal && (
|
||||||
|
<UpgradeAccountModal
|
||||||
|
onClose={() => {
|
||||||
|
setShowUpgradeModal(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{isPersonalizeOpen && (
|
{isPersonalizeOpen && (
|
||||||
<UpdatePersonaModal
|
<UpdatePersonaModal
|
||||||
roadmapId={roadmapId}
|
roadmapId={roadmapId}
|
||||||
@@ -366,6 +376,12 @@ export function RoadmapFloatingChat(props: RoadmapChatProps) {
|
|||||||
key={`default-question-${index}`}
|
key={`default-question-${index}`}
|
||||||
className="flex h-full self-start rounded-md bg-yellow-500/10 px-3 py-2 text-left text-sm text-black hover:bg-yellow-500/20"
|
className="flex h-full self-start rounded-md bg-yellow-500/10 px-3 py-2 text-left text-sm text-black hover:bg-yellow-500/20"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (isLimitExceeded) {
|
||||||
|
setShowUpgradeModal(true);
|
||||||
|
setIsOpen(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
handleChatSubmit(
|
handleChatSubmit(
|
||||||
textToJSON(question),
|
textToJSON(question),
|
||||||
isRoadmapDetailLoading,
|
isRoadmapDetailLoading,
|
||||||
@@ -415,7 +431,8 @@ export function RoadmapFloatingChat(props: RoadmapChatProps) {
|
|||||||
{isLimitExceeded && (
|
{isLimitExceeded && (
|
||||||
<UpgradeMessage
|
<UpgradeMessage
|
||||||
onUpgradeClick={() => {
|
onUpgradeClick={() => {
|
||||||
window.open('/premium', '_blank');
|
setShowUpgradeModal(true);
|
||||||
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -436,7 +453,8 @@ export function RoadmapFloatingChat(props: RoadmapChatProps) {
|
|||||||
<UsageButton
|
<UsageButton
|
||||||
percentageUsed={percentageUsed}
|
percentageUsed={percentageUsed}
|
||||||
onUpgradeClick={() => {
|
onUpgradeClick={() => {
|
||||||
window.open('/premium', '_blank');
|
setShowUpgradeModal(true);
|
||||||
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@@ -2,6 +2,7 @@ import { type ReactNode, useRef } from 'react';
|
|||||||
import { useOutsideClick } from '../hooks/use-outside-click';
|
import { useOutsideClick } from '../hooks/use-outside-click';
|
||||||
import { useKeydown } from '../hooks/use-keydown';
|
import { useKeydown } from '../hooks/use-keydown';
|
||||||
import { cn } from '../lib/classname';
|
import { cn } from '../lib/classname';
|
||||||
|
import { X } from 'lucide-react';
|
||||||
|
|
||||||
type ModalProps = {
|
type ModalProps = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -9,6 +10,7 @@ type ModalProps = {
|
|||||||
overlayClassName?: string;
|
overlayClassName?: string;
|
||||||
bodyClassName?: string;
|
bodyClassName?: string;
|
||||||
wrapperClassName?: string;
|
wrapperClassName?: string;
|
||||||
|
hasCloseButton?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Modal(props: ModalProps) {
|
export function Modal(props: ModalProps) {
|
||||||
@@ -18,6 +20,7 @@ export function Modal(props: ModalProps) {
|
|||||||
bodyClassName,
|
bodyClassName,
|
||||||
wrapperClassName,
|
wrapperClassName,
|
||||||
overlayClassName,
|
overlayClassName,
|
||||||
|
hasCloseButton = true,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const popupBodyEl = useRef<HTMLDivElement>(null);
|
const popupBodyEl = useRef<HTMLDivElement>(null);
|
||||||
@@ -33,7 +36,7 @@ export function Modal(props: ModalProps) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'fixed left-0 right-0 top-0 z-99 flex h-full items-center justify-center overflow-y-auto overflow-x-hidden bg-black/50',
|
'fixed top-0 right-0 left-0 z-99 flex h-full items-center justify-center overflow-x-hidden overflow-y-auto bg-black/50',
|
||||||
overlayClassName,
|
overlayClassName,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -50,6 +53,14 @@ export function Modal(props: ModalProps) {
|
|||||||
bodyClassName,
|
bodyClassName,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
{hasCloseButton && (
|
||||||
|
<button
|
||||||
|
onClick={onClose}
|
||||||
|
className="absolute top-4 right-4 text-gray-300 hover:text-gray-700"
|
||||||
|
>
|
||||||
|
<X className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user