mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-25 00:21:28 +02:00
feat: create new course
This commit is contained in:
committed by
Kamran Ahmed
parent
30d3a86784
commit
646cc3c826
54
src/components/TopicDetail/CreateCourseModal.tsx
Normal file
54
src/components/TopicDetail/CreateCourseModal.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { ChevronRightIcon, SearchIcon } from 'lucide-react';
|
||||
import { Modal } from '../Modal';
|
||||
|
||||
type CreateCourseModalProps = {
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
export function CreateCourseModal(props: CreateCourseModalProps) {
|
||||
const { onClose } = props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
onClose={onClose}
|
||||
wrapperClassName="h-auto mt-20"
|
||||
overlayClassName="items-start"
|
||||
bodyClassName="p-1.5"
|
||||
>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(e.target as HTMLFormElement);
|
||||
const subject = formData.get('subject');
|
||||
|
||||
window.location.href = `/ai/search?term=${subject}&difficulty=beginner&src=topic`;
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<label
|
||||
className="mb-2.5 ml-1 inline-block text-sm leading-none"
|
||||
htmlFor="subject"
|
||||
>
|
||||
Subject
|
||||
</label>
|
||||
<div className="relative overflow-hidden rounded-lg border">
|
||||
<input
|
||||
id="subject"
|
||||
type="text"
|
||||
className="w-full bg-white p-2.5 px-8 text-sm focus:bg-gray-50 focus:outline-hidden"
|
||||
placeholder="Enter a Subject for the Course"
|
||||
name="subject"
|
||||
autoFocus={true}
|
||||
/>
|
||||
|
||||
<div className="absolute top-0 left-0 flex h-full items-center justify-center px-2 text-gray-500">
|
||||
<SearchIcon className="size-4" />
|
||||
</div>
|
||||
<button className="absolute top-0 right-0 flex h-full items-center justify-center px-2 hover:bg-gray-200">
|
||||
<ChevronRightIcon className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@@ -42,6 +42,7 @@ import { cn } from '../../lib/classname.ts';
|
||||
import type { AIChatHistoryType } from '../GenerateCourse/AICourseLessonChat.tsx';
|
||||
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';
|
||||
import { TopicProgressButton } from './TopicProgressButton.tsx';
|
||||
import { CreateCourseModal } from './CreateCourseModal.tsx';
|
||||
|
||||
type TopicDetailProps = {
|
||||
resourceId?: string;
|
||||
@@ -119,6 +120,8 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
||||
const [isCustomResource, setIsCustomResource] = useState(false);
|
||||
|
||||
const [showSubjectSearchModal, setShowSubjectSearchModal] = useState(false);
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const [showPaidResourceDisclaimer, setShowPaidResourceDisclaimer] =
|
||||
@@ -139,6 +142,7 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
setShowUpgradeModal(false);
|
||||
setAiChatHistory(defaultChatHistory);
|
||||
setActiveTab('content');
|
||||
setShowSubjectSearchModal(false);
|
||||
};
|
||||
|
||||
// Close the topic detail when user clicks outside the topic detail
|
||||
@@ -349,10 +353,6 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const resourceTitleForSearch = resourceTitle
|
||||
?.toLowerCase()
|
||||
?.replace(/\s+?roadmap/gi, '');
|
||||
|
||||
const tnsLink =
|
||||
'https://thenewstack.io/devops/?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Topic';
|
||||
|
||||
@@ -362,10 +362,6 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
return resource.topicIds.includes(normalizedTopicId);
|
||||
});
|
||||
|
||||
const hasPaidScrimbaLinks = paidResourcesForTopic.some(
|
||||
(resource) => resource?.url?.toLowerCase().indexOf('scrimba') !== -1,
|
||||
);
|
||||
|
||||
const shouldShowAiTab = !isCustomResource && resourceType === 'roadmap';
|
||||
|
||||
return (
|
||||
@@ -379,6 +375,10 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
<UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />
|
||||
)}
|
||||
|
||||
{showSubjectSearchModal && (
|
||||
<CreateCourseModal onClose={() => setShowSubjectSearchModal(false)} />
|
||||
)}
|
||||
|
||||
{isLoading && (
|
||||
<div className="flex h-full w-full justify-center">
|
||||
<Spinner
|
||||
@@ -448,6 +448,14 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
handleClose();
|
||||
showLoginPopup();
|
||||
}}
|
||||
onShowSubjectSearchModal={() => {
|
||||
if (!isLoggedIn()) {
|
||||
showLoginPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
setShowSubjectSearchModal(true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@@ -11,6 +11,8 @@ import {
|
||||
Gift,
|
||||
Loader2Icon,
|
||||
LockIcon,
|
||||
PlusIcon,
|
||||
SearchIcon,
|
||||
SendIcon,
|
||||
Trash2,
|
||||
} from 'lucide-react';
|
||||
@@ -42,6 +44,8 @@ type TopicDetailAIProps = {
|
||||
|
||||
onUpgrade: () => void;
|
||||
onLogin: () => void;
|
||||
|
||||
onShowSubjectSearchModal: () => void;
|
||||
};
|
||||
|
||||
export function TopicDetailAI(props: TopicDetailAIProps) {
|
||||
@@ -53,6 +57,7 @@ export function TopicDetailAI(props: TopicDetailAIProps) {
|
||||
topicId,
|
||||
onUpgrade,
|
||||
onLogin,
|
||||
onShowSubjectSearchModal,
|
||||
} = props;
|
||||
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
@@ -298,6 +303,14 @@ export function TopicDetailAI(props: TopicDetailAIProps) {
|
||||
))}
|
||||
</a>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={onShowSubjectSearchModal}
|
||||
className="flex items-center gap-1.5 rounded-md border border-gray-300 bg-transparent px-2 py-1 hover:bg-gray-200 hover:text-black"
|
||||
>
|
||||
<PlusIcon className="h-3 w-3" />
|
||||
Create a Course
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
Reference in New Issue
Block a user