mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2026-09-24 15:00:31 +08:00
* Update * Add stats and health endpoints * Add pre-render * fix: redirect to the error page * Fix generate-renderer issue * Rename * Fix best practice topics not loading * Handle SSR for static pages * Refactor faqs * Refactor best practices * Fix absolute import * Fix stats * Add custom roadmap page * Minor UI change * feat: custom roadmap slug routes (#4987) * feat: replace roadmap slug * fix: remove roadmap slug * feat: username route * fix: user public page * feat: show roadmap progress * feat: update public profile * fix: replace with toast * feat: user public profile page * feat: implement profile form * feat: implement user profile roadmap page * refactor: remove logs * fix: increase progress gap * fix: remove title margin * fix: breakpoint for roadmaps * Update dependencies * Upgrade dependencies * fix: improper avatars * fix: heatmap focus * wip: remove `getStaticPaths` * fix: add disable props * wip * feat: add email icon * fix: update pnpm lock * fix: implement author page * Fix beginner roadmaps not working * Changes to form * Refactor profile and form * Refactor public profile form * Rearrange sidebar items * Update UI for public form * Minor text update * Refactor public profile form * Error page for user * Revamp UI for profile page * Add public profile page * Fix vite warnings * Add private profile banner * feat: on blur check username * Update fetch depth * Add error detail * Use hybrid mode of rendering * Do not pre-render stats pages * Update deployment workflow * Update deployment workflow --------- Co-authored-by: Arik Chakma <arikchangma@gmail.com>
146 lines
3.9 KiB
TypeScript
146 lines
3.9 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { httpGet, httpPost } from '../../lib/http';
|
|
import { useToast } from '../../hooks/use-toast';
|
|
import { isLoggedIn } from '../../lib/jwt';
|
|
import { GitFork, Loader2, Map } from 'lucide-react';
|
|
import { showLoginPopup } from '../../lib/popup';
|
|
import type { RoadmapDocument } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal.tsx';
|
|
|
|
type CreateVersionProps = {
|
|
roadmapId: string;
|
|
};
|
|
|
|
export function CreateVersion(props: CreateVersionProps) {
|
|
const { roadmapId } = props;
|
|
|
|
const toast = useToast();
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [isCreating, setIsCreating] = useState(false);
|
|
const [isConfirming, setIsConfirming] = useState(false);
|
|
const [userVersion, setUserVersion] = useState<RoadmapDocument>();
|
|
|
|
async function loadMyVersion() {
|
|
if (!isLoggedIn()) {
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
const { response, error } = await httpGet<RoadmapDocument>(
|
|
`${import.meta.env.PUBLIC_API_URL}/v1-get-my-version/${roadmapId}`,
|
|
{},
|
|
);
|
|
|
|
if (error || !response) {
|
|
setIsLoading(false);
|
|
return;
|
|
}
|
|
|
|
setIsLoading(false);
|
|
setUserVersion(response);
|
|
}
|
|
|
|
useEffect(() => {
|
|
loadMyVersion().finally(() => {
|
|
setIsLoading(false);
|
|
});
|
|
}, []);
|
|
|
|
async function createVersion() {
|
|
if (isCreating || !roadmapId) {
|
|
return;
|
|
}
|
|
|
|
if (!isLoggedIn()) {
|
|
showLoginPopup();
|
|
return;
|
|
}
|
|
|
|
setIsCreating(true);
|
|
const { response, error } = await httpPost<{ roadmapId: string }>(
|
|
`${import.meta.env.PUBLIC_API_URL}/v1-create-version/${roadmapId}`,
|
|
{},
|
|
);
|
|
|
|
if (error || !response) {
|
|
setIsCreating(false);
|
|
toast.error(error?.message || 'Failed to create version');
|
|
return;
|
|
}
|
|
|
|
window.location.href = `${
|
|
import.meta.env.PUBLIC_EDITOR_APP_URL
|
|
}/${response?.roadmapId}`;
|
|
}
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="h-[30px] w-[312px] animate-pulse rounded-md bg-gray-300"></div>
|
|
);
|
|
}
|
|
|
|
if (!isLoading && userVersion?._id) {
|
|
return (
|
|
<div className={'flex items-center'}>
|
|
<a
|
|
href={`/r/${userVersion?.slug}`}
|
|
className="flex items-center rounded-md border border-blue-400 bg-gray-50 px-2.5 py-1 text-xs font-medium text-blue-600 hover:bg-blue-100 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:hover:bg-gray-100 max-sm:hidden sm:text-sm"
|
|
>
|
|
<Map size="15px" className="mr-1.5" />
|
|
Visit your own version of this Roadmap
|
|
</a>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (isConfirming) {
|
|
return (
|
|
<p className="flex h-[30px] items-center text-sm text-red-500">
|
|
Create and edit a custom roadmap from this roadmap?
|
|
<button
|
|
onClick={() => {
|
|
setIsConfirming(false);
|
|
createVersion().finally(() => null);
|
|
}}
|
|
className="ml-2 font-semibold underline underline-offset-2"
|
|
>
|
|
Yes
|
|
</button>
|
|
<span className="text-xs"> / </span>
|
|
<button
|
|
className="font-semibold underline underline-offset-2"
|
|
onClick={() => setIsConfirming(false)}
|
|
>
|
|
No
|
|
</button>
|
|
</p>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<button
|
|
disabled={isCreating}
|
|
className="flex items-center justify-center rounded-md border border-gray-300 bg-gray-50 px-2.5 py-1 text-xs font-medium text-black hover:bg-gray-200 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:hover:bg-gray-100 max-sm:hidden sm:text-sm"
|
|
onClick={() => {
|
|
if (!isLoggedIn()) {
|
|
showLoginPopup();
|
|
return;
|
|
}
|
|
|
|
setIsConfirming(true);
|
|
}}
|
|
>
|
|
{isCreating ? (
|
|
<>
|
|
<Loader2 className="mr-2 h-3 w-3 animate-spin stroke-[2.5]" />
|
|
Please wait ..
|
|
</>
|
|
) : (
|
|
<>
|
|
<GitFork className="mr-1.5" size="16px" />
|
|
Create your own version of this roadmap
|
|
</>
|
|
)}
|
|
</button>
|
|
);
|
|
}
|