mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2026-03-12 17:51:53 +08:00
* wip: courses * fix: update course sidebar * wip * fix: merge lessons * wip * wip: course footer * wip * fix: refactor layout * fix: refactor * feat: course progress * fix: update current lesson store * fix: refactor props * wip * wip * feat: course certificate * wip: course rating * wip: course notes * wip * feat: implement course notes * feat: make card clickable * fix: add hover background * fix: refactor course layout * fix: resizeable * fix: go back on save * feat: delete confimation * wip * feat: chat UI * fix: lesson complete guard issue * wip: add public json files * wip: course ai * fix: loading card * Fix failing dev without internet * Light mode and UI changes * Update UI * Update course UI * Add chapter page * Improve sidebar of course * Update navigation: * Update quiz view * Improve UI for quiz attempts * Remove unnecessary console.logs * Add progress loading skeletons * Update UI * Change background color of editor * Fix line color not applied on editor * UI updates * feat: empty view * feat: course ai token limit * feat: handle auth users * wip * feat: course landing page * wip * Add first chapter of SQL * Add introduction chapter * Add quiz for introduction * Add expressions in select * Add content for DISTINCT * Add filter with where * Add lesson about limit and offset * Add lesson for handling null values * Add lesson about comments * Add challenges * Add challenge * Add challenge * Add challenge * Add challenge 7 * Add creating tables lesson * Add common data types lesson * Add data types in sqlite * Add more on data types lesson * feat: course landing page * Add more on numeric types * Update * Add lesson about temporal data types * Add constraints * Add primary keys chapter * Add modifying tables * Add dropping and truncating * Rewrite for PostgreSQL * Update numeric types to PostgreSQL * Improve temporal data type content * Improve temporal data type content * Add setup for temporal data * Improve challenges in SQL basics * Update challenge names * Add new challenges * Add temporal validation challenge * Add new constraint * Add modifying tables query * Removing table * Add insert operations lesson * Add updating data lesson * Add delete operations * Add inserting and updating challenges * Add lesson for cleaning up data * Update course title * Add relation data lesson * Add relationships and types * Add relationships and types * wip * Add joins lesson * Joins in queries * Add inner join details * Add join queries * Add inner join details * Add foreign key constraint lesson * Update composite foreign keys * Add lesson about foreign keys * Add lesson about set operation queries * Add lesson about set operation queries * Add set operator challenges * Add new challenge * Add view lesson * Add notes in views * Add inactive customer challenge * Add high value order challenge * gst * Add new challenges * Add readers like you challenge * Update inactive customer query * Update inactive customer query * Update inactive customer query * Update inactive customer query * Update inactive customer query * add challenge for same price books * Add aggregate functions introduction * Add basic aggregation lesson * Add basic aggregation lesson * Add introduction quiz * Add grouping lesson * Add grouping gotchas * Add grouping and filtering lesson * Add note for lesson * Add challenges for aggregate * Update aggregate challenge * Rearrange chapters * Add scalar functions lessons * Add numeric functions * Add date functions * Add conversion functions * Add conversion functions * Add logical functions chapter * Add exercises * Add new challenges * Add monthly sales analysis * Add subqueries and ctes * Update * Add correlated subqueries * Add common table expressions * Add common-table expressions * Add example * Add recursive CTEs * Add subquery challenge * Add latest category books challenge * Add challenges * Add bestseller rankings challenge * Add new customer analysis * Add daily sales report * Improve queries * Add introduction to window functions * Add over and partition * wip: billing page * Add ranking functions * Improve ranking functions * Add order by * Add window frames lesson * Add window frames explanation * Add challenges for window functions * Add price range analysis challenge * wip * wip: course enroll * fix: start learning * wip * wip * Enrollment changes * wip * wip * feat: mobile responsive * Changelog banner refactor * Update * Header for course * Header for what to expect * UI color * Table of contents * Icons on chapters * Change design for road to sql * Add sql course page * Add lesson content * Update UI * Expanded chapter row * Add course page * Refactor * Add spotlight * Improve features * Add course features * Add certificate note * Zoom in on the image * Update * Add floating purchase * Floating purchase indicatorg * Add about section * Update about section * Add FAQ section * Update UI * Add purchase power parity * Show purchasing power pricing * Add course login popup * Add course login popup * Add account button * Add trigger for course purchase * Course purchase param * Buy button changes * Add faqs * Add purchase trigger on reload * Landing verification * Make header responsive * Make course page upper half responsive * Full page is responsive * Fix login height bug * Responsiveness * Implement login after checkout * Remove unused code * Update dependenciesg * Update * fix: refetch mount to false * Remove unused code * Remove unused code * Remove unused code * Remove unused code * Remove unused code * Remove unused code * Remove unused * Add quizzes to chapters * Update course slug * Update dependencies * Add header for sql course --------- Co-authored-by: Arik Chakma <arikchangma@gmail.com>
144 lines
4.4 KiB
TypeScript
144 lines
4.4 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { Modal } from '../Modal';
|
|
import { GitHubButton } from './GitHubButton';
|
|
import { GoogleButton } from './GoogleButton';
|
|
import { LinkedInButton } from './LinkedInButton';
|
|
import { EmailLoginForm } from './EmailLoginForm';
|
|
import { EmailSignupForm } from './EmailSignupForm';
|
|
|
|
type CourseLoginPopupProps = {
|
|
onClose: () => void;
|
|
checkoutAfterLogin?: boolean;
|
|
};
|
|
|
|
export const CHECKOUT_AFTER_LOGIN_KEY = 'checkoutAfterLogin';
|
|
|
|
export function CourseLoginPopup(props: CourseLoginPopupProps) {
|
|
const { onClose: parentOnClose, checkoutAfterLogin = true } = props;
|
|
|
|
const [isDisabled, setIsDisabled] = useState(false);
|
|
const [isUsingEmail, setIsUsingEmail] = useState(false);
|
|
|
|
const [emailNature, setEmailNature] = useState<'login' | 'signup' | null>(
|
|
null,
|
|
);
|
|
|
|
function onClose() {
|
|
// if user didn't login and closed the popup, we remove the checkoutAfterLogin flag
|
|
// so that login from other buttons on course page will trigger purchase
|
|
localStorage.removeItem(CHECKOUT_AFTER_LOGIN_KEY);
|
|
parentOnClose();
|
|
}
|
|
|
|
useEffect(() => {
|
|
localStorage.setItem(
|
|
CHECKOUT_AFTER_LOGIN_KEY,
|
|
checkoutAfterLogin ? '1' : '0',
|
|
);
|
|
}, [checkoutAfterLogin]);
|
|
|
|
if (emailNature) {
|
|
const emailHeader = (
|
|
<div className="mb-7 text-center">
|
|
<p className="mb-3.5 pt-2 text-2xl font-semibold leading-5 text-slate-900">
|
|
{emailNature === 'login'
|
|
? 'Login to your account'
|
|
: 'Create an account'}
|
|
</p>
|
|
<p className="mt-2 text-sm leading-4 text-slate-600">
|
|
Fill in the details below to continue
|
|
</p>
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<Modal onClose={onClose} bodyClassName="p-5 h-auto">
|
|
{emailHeader}
|
|
{emailNature === 'login' && (
|
|
<EmailLoginForm
|
|
isDisabled={isDisabled}
|
|
setIsDisabled={setIsDisabled}
|
|
/>
|
|
)}
|
|
{emailNature === 'signup' && (
|
|
<EmailSignupForm
|
|
isDisabled={isDisabled}
|
|
setIsDisabled={setIsDisabled}
|
|
/>
|
|
)}
|
|
|
|
<button
|
|
className="mt-2 w-full rounded-md border border-gray-400 py-2 text-center text-sm text-gray-600 hover:bg-gray-100"
|
|
onClick={() => setEmailNature(null)}
|
|
>
|
|
Back to Options
|
|
</button>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Modal onClose={onClose} bodyClassName="p-5 h-auto">
|
|
<div className="mb-7 text-center">
|
|
<p className="mb-3.5 pt-2 text-2xl font-semibold leading-5 text-slate-900">
|
|
Create or login to your account
|
|
</p>
|
|
<p className="mt-2 text-sm leading-4 text-slate-600">
|
|
Login or sign up for an account to start learning
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex w-full flex-col gap-2">
|
|
<GitHubButton
|
|
className="rounded-md border-gray-400 hover:bg-gray-100"
|
|
isDisabled={isDisabled}
|
|
setIsDisabled={setIsDisabled}
|
|
/>
|
|
<GoogleButton
|
|
className="rounded-md border-gray-400 hover:bg-gray-100"
|
|
isDisabled={isDisabled}
|
|
setIsDisabled={setIsDisabled}
|
|
/>
|
|
<LinkedInButton
|
|
className="rounded-md border-gray-400 hover:bg-gray-100"
|
|
isDisabled={isDisabled}
|
|
setIsDisabled={setIsDisabled}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex w-full items-center gap-4 py-6 text-sm text-gray-600">
|
|
<div className="h-px w-full bg-gray-200" />
|
|
OR
|
|
<div className="h-px w-full bg-gray-200" />
|
|
</div>
|
|
|
|
<div className="flex flex-row gap-2">
|
|
{!isUsingEmail && (
|
|
<button
|
|
className="flex-grow rounded-md border border-gray-400 px-4 py-2 text-sm text-gray-600 hover:bg-gray-100"
|
|
onClick={() => setIsUsingEmail(true)}
|
|
>
|
|
Use your email address
|
|
</button>
|
|
)}
|
|
{isUsingEmail && (
|
|
<>
|
|
<button
|
|
className="flex-grow rounded-md border border-gray-400 px-4 py-2 text-sm text-gray-600 hover:bg-gray-100"
|
|
onClick={() => setEmailNature('login')}
|
|
>
|
|
Already have an account
|
|
</button>
|
|
<button
|
|
className="flex-grow rounded-md border border-gray-400 px-4 py-2 text-sm text-gray-600 hover:bg-gray-100"
|
|
onClick={() => setEmailNature('signup')}
|
|
>
|
|
Create an account
|
|
</button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</Modal>
|
|
);
|
|
}
|