computer-scienceangular-roadmapbackend-roadmapblockchain-roadmapdba-roadmapdeveloper-roadmapdevops-roadmapfrontend-roadmapgo-roadmaphactoberfestjava-roadmapjavascript-roadmapnodejs-roadmappython-roadmapqa-roadmapreact-roadmaproadmapstudy-planvue-roadmapweb3-roadmap
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
4.9 KiB
155 lines
4.9 KiB
import { Check, CopyIcon, ServerCrash } from 'lucide-react'; |
|
import { Modal } from '../Modal'; |
|
import { getRelativeTimeString } from '../../lib/date'; |
|
import { useEffect, useState } from 'react'; |
|
import { Spinner } from '../ReactIcons/Spinner.tsx'; |
|
import { httpPost } from '../../lib/http.ts'; |
|
import { CheckIcon } from '../ReactIcons/CheckIcon.tsx'; |
|
import { useCopyText } from '../../hooks/use-copy-text.ts'; |
|
|
|
type StartProjectModalProps = { |
|
projectId: string; |
|
onClose: () => void; |
|
startedAt?: Date; |
|
onStarted: (startedAt: Date) => void; |
|
}; |
|
|
|
export function StartProjectModal(props: StartProjectModalProps) { |
|
const { onClose, startedAt, onStarted, projectId } = props; |
|
|
|
const [isStartingProject, setIsStartingProject] = useState(true); |
|
const [error, setError] = useState<string | null>(); |
|
|
|
const { isCopied, copyText } = useCopyText(); |
|
|
|
const projectUrl = `${import.meta.env.PUBLIC_APP_URL}/projects/${projectId}`; |
|
|
|
const formattedStartedAt = startedAt ? getRelativeTimeString(startedAt) : ''; |
|
|
|
async function handleStartProject() { |
|
if (!projectId || startedAt) { |
|
return; |
|
} |
|
|
|
setIsStartingProject(true); |
|
const { response, error } = await httpPost<{ |
|
startedAt: Date; |
|
}>(`${import.meta.env.PUBLIC_API_URL}/v1-start-project/${projectId}`, {}); |
|
|
|
if (error || !response) { |
|
setError(error?.message || 'Failed to start project'); |
|
setIsStartingProject(false); |
|
return; |
|
} |
|
|
|
onStarted(response.startedAt); |
|
} |
|
|
|
useEffect(() => { |
|
handleStartProject().finally(() => setIsStartingProject(false)); |
|
}, []); |
|
|
|
if (error) { |
|
return ( |
|
<Modal onClose={onClose} bodyClassName="h-auto text-red-500"> |
|
<div className="flex flex-col items-center justify-center gap-2 pt-12 pb-10"> |
|
<ServerCrash className={'h-6 w-6'} /> |
|
<p className="font-medium">{error}</p> |
|
</div> |
|
</Modal> |
|
); |
|
} |
|
|
|
if (isStartingProject) { |
|
return ( |
|
<Modal onClose={onClose} bodyClassName="h-auto"> |
|
<div className="flex flex-col items-center justify-center gap-4 pt-12 pb-10"> |
|
<Spinner className={'h-6 w-6'} isDualRing={false} /> |
|
<p className="font-medium">Starting project ..</p> |
|
</div> |
|
</Modal> |
|
); |
|
} |
|
|
|
return ( |
|
<Modal |
|
onClose={onClose} |
|
bodyClassName="h-auto p-4 relative overflow-hidden" |
|
wrapperClassName={'max-w-md'} |
|
> |
|
<p className="-mx-4 -mt-4 flex items-center bg-yellow-200 px-3 py-2 text-sm text-yellow-900"> |
|
<CheckIcon additionalClasses="mr-1.5 w-[15px] text-yellow-800 h-[15px]" /> |
|
<span className="mr-1.5 font-normal">Project started</span>{' '} |
|
<span className="font-semibold">{formattedStartedAt}</span> |
|
</p> |
|
<h2 className="mt-5 mb-1 text-2xl font-semibold text-gray-800"> |
|
Start Building |
|
</h2> |
|
<p className="text-gray-700"> |
|
Follow these steps to complete the project. |
|
</p> |
|
|
|
<div className="my-5 space-y-1.5 marker:text-gray-400"> |
|
<p className="mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900"> |
|
1. Create a new public repository on GitHub. |
|
</p> |
|
|
|
<p className="mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900"> |
|
2. Complete the project according to the requirements and push your |
|
code to the GitHub repository. |
|
</p> |
|
|
|
<p className="mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900"> |
|
3. Add a README file with instructions to run the project and the{' '} |
|
<button |
|
onClick={() => { |
|
copyText(projectUrl); |
|
}} |
|
className="font-semibold" |
|
> |
|
{!isCopied && ( |
|
<span className="text-purple-600"> |
|
project page URL |
|
<CopyIcon |
|
className="relative -top-px ml-1 inline-block h-4 w-4" |
|
strokeWidth={2.5} |
|
/> |
|
</span> |
|
)} |
|
{isCopied && ( |
|
<> |
|
copied URL |
|
<Check className="inline-block h-4 w-4" strokeWidth={2.5} /> |
|
</> |
|
)} |
|
</button> |
|
</p> |
|
<p className="mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900"> |
|
4. Once done, submit your solution to help the others learn and get |
|
feedback from the community. |
|
</p> |
|
</div> |
|
|
|
<div className="mb-5"> |
|
<p className="text-sm"> |
|
If you get stuck, you can always ask for help in the community{' '} |
|
<a |
|
href="https://roadmap.sh/discord" |
|
target="_blank" |
|
className="font-medium underline underline-offset-2" |
|
> |
|
chat on discord |
|
</a> |
|
. |
|
</p> |
|
</div> |
|
|
|
<button |
|
className="w-full rounded-md bg-black py-2 text-sm font-medium text-white hover:bg-gray-900" |
|
onClick={onClose} |
|
> |
|
Close |
|
</button> |
|
</Modal> |
|
); |
|
}
|
|
|