import { type FormEvent, type MouseEvent, useEffect, useRef, useState, } from 'react'; import { Loader2 } from 'lucide-react'; import { Modal } from '../../Modal'; import { useToast } from '../../../hooks/use-toast'; import { httpPost } from '../../../lib/http'; import { cn } from '../../../lib/classname'; export const allowedRoadmapVisibility = [ 'me', 'friends', 'team', 'public', ] as const; export type AllowedRoadmapVisibility = (typeof allowedRoadmapVisibility)[number]; export const allowedCustomRoadmapType = ['role', 'skill'] as const; export type AllowedCustomRoadmapType = (typeof allowedCustomRoadmapType)[number]; export const allowedShowcaseStatus = [ 'submitted', 'approved', 'rejected', 'rejected_with_reason', ] as const; export type AllowedShowcaseStatus = (typeof allowedShowcaseStatus)[number]; export interface RoadmapDocument { _id: string; title: string; description?: string; slug?: string; creatorId: string; aiRoadmapId?: string; teamId?: string; topicCount: number; visibility: AllowedRoadmapVisibility; sharedFriendIds?: string[]; sharedTeamMemberIds?: string[]; feedbacks?: { userId: string; email: string; feedback: string; }[]; metadata?: { originalRoadmapId?: string; defaultRoadmapId?: string; }; nodes: any[]; edges: any[]; isDiscoverable?: boolean; ratings: { average: number; totalCount: number; breakdown: { [key: number]: number; }; }; showcaseStatus?: AllowedShowcaseStatus; showcaseRejectedReason?: string; showcaseRejectedAt?: Date; showcaseSubmittedAt?: Date; showcaseApprovedAt?: Date; hasMigratedContent?: boolean; createdAt: Date; updatedAt: Date; } interface CreateRoadmapModalProps { onClose: () => void; onCreated?: (roadmap: RoadmapDocument) => void; teamId?: string; visibility?: AllowedRoadmapVisibility; } export function CreateRoadmapModal(props: CreateRoadmapModalProps) { const { onClose, onCreated, teamId } = props; const titleRef = useRef(null); const toast = useToast(); const [isLoading, setIsLoading] = useState(false); const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const isInvalidDescription = description?.trim().length > 80; async function handleSubmit( e: FormEvent | MouseEvent, redirect: boolean = true, ) { e.preventDefault(); if (isLoading) { return; } if (title.trim() === '' || isInvalidDescription) { toast.error('Please fill all the fields'); return; } setIsLoading(true); const { response, error } = await httpPost( `${import.meta.env.PUBLIC_API_URL}/v1-create-roadmap`, { title, description, ...(teamId && { teamId, }), nodes: [], edges: [], }, ); if (error) { setIsLoading(false); toast.error(error?.message || 'Something went wrong, please try again'); return; } toast.success('Roadmap created successfully'); if (redirect) { window.location.href = `${ import.meta.env.PUBLIC_EDITOR_APP_URL }/${response?._id}`; return; } if (onCreated) { onCreated(response as RoadmapDocument); return; } onClose(); setTitle(''); setDescription(''); setIsLoading(false); } useEffect(() => { titleRef.current?.focus(); }, []); return (

Create Roadmap

Add a title and description to your roadmap.

setTitle(e.target.value)} />