Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yadavshubham01 committed Nov 23, 2024
0 parents commit ad4f403
Show file tree
Hide file tree
Showing 100 changed files with 17,780 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local
.env
# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
11 changes: 11 additions & 0 deletions app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, { ReactNode } from 'react'

const AuthLayout = ({children} : {children : ReactNode}) => {
return (
<div className='flex items-center justify-center w-full h-screen'>
{children}
</div>
)
}

export default AuthLayout
10 changes: 10 additions & 0 deletions app/(auth)/sign-in/[[...sign-in]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SignIn } from "@clerk/nextjs";
import AuthLayout from "../../layout";

export default function Page() {
return (
<AuthLayout>
<SignIn />
</AuthLayout>
);
}
10 changes: 10 additions & 0 deletions app/(auth)/sign-up/[[...sign-up]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SignUp } from "@clerk/nextjs";
import AuthLayout from "../../layout";

export default function Page() {
return (
<AuthLayout>
<SignUp />
</AuthLayout>
);
}
209 changes: 209 additions & 0 deletions app/(resume)/build-resume/[id]/(edit)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
"use client";

import { useParams, usePathname, useSearchParams } from "next/navigation";
import { useUser } from "@clerk/nextjs";
import { useQuery } from "convex/react";
import { useRouter } from "nextjs-toploader/app";
import React from "react";
import toast from "react-hot-toast";

import LiveResumePreview from "@/components/LiveResumePreview";
import VerticalTimeline from "@/components/VerticalTimeline";
import ContineBtn from "@/components/ContineBtn";
import { api } from "@/convex/_generated/api";
import { Id } from "@/convex/_generated/dataModel";
import { geologicaFont } from "@/lib/font";
import { cn } from "@/lib/utils";
import { motion } from "framer-motion";
import { item } from "@/lib/motion";
import useMobile from "@/lib/useMobile";
import MobilePreviewButton from "@/components/MobilePreviewButton";
import PreviewModal from "@/components/PreviewModal";
import { ResumeTemplate } from "@/types/templateTypes";
import { Button } from "@/components/ui/button";

// Types
type Section =
| "header"
| "experience"
| "skills"
| "education"
| "projects"
| "custom"
| "final";
type ResumeSection = {
type: Section;
};

interface ResumeData {
userId: string;
sections: ResumeSection[];
}

interface ResumeBuilderLayoutProps {
children: React.ReactNode;
}

// Constants
const POSSIBLE_SECTIONS: readonly Section[] = [
"header",
"experience",
"skills",
"education",
"projects",
"custom",
"final",
];

const ResumeBuilderLayout: React.FC<ResumeBuilderLayoutProps> = ({
children,
}) => {
// Hooks
const params = useParams();
const router = useRouter();
const { user, isLoaded } = useUser();
const searchParams = useSearchParams();
const pathname = usePathname();
const isMobile = useMobile();

const resumeId = params.id as Id<"resumes">;
const resume = useQuery(api.resume.getTemplateDetails, { id: resumeId });

// Helper functions
const validateSection = (section: string): section is Section => {
return POSSIBLE_SECTIONS.includes(section as Section);
};

const getNavigationUrls = (
sectionArray: Section[],
currentSection: string | null,
pathname: string
): { prevUrl: string; nextUrl: string } => {
if (currentSection) {
return handleSearchParamNavigation(sectionArray, currentSection);
}
return handlePathNavigation(sectionArray, pathname);
};

const handleSearchParamNavigation = (
sectionArray: Section[],
sec: string
) => {
const index = sectionArray.findIndex((item) => item === sec);
const nextSection = sec === "custom" ? "custom" : sectionArray[index];
const prevSection = sectionArray[index - 1] ?? "header";

return {
nextUrl: `/build-resume/${resumeId}/section/${nextSection}`,
prevUrl:
sec === "header"
? `/build-resume/${resumeId}/tips?sec=header`
: `/build-resume/${resumeId}/section/${prevSection}`,
};
};

const handlePathNavigation = (sectionArray: Section[], pathname: string) => {
const sectionType = pathname.split("/section/")[1] as Section;
const currentIndex = sectionArray.findIndex((item) => item === sectionType);

return {
prevUrl:
sectionType === "final"
? `/build-resume/${resumeId}/tips?sec=custom`
: `/build-resume/${resumeId}/tips?sec=${sectionArray[currentIndex]}`,
nextUrl:
sectionType === "custom"
? `/build-resume/${resumeId}/section/final`
: sectionType === "final"
? `/build-resume/${resumeId}/download`
: `/build-resume/${resumeId}/tips?sec=${sectionArray[currentIndex + 1]}`,
};
};

// Error handling and validation
if (resume === undefined) return null;
if (resume === null) return <div>Template not found</div>;
if (isLoaded && resume?.userId !== user?.id) {
toast.error("Not authenticated");
router.push("/");
return null;
}

const sectionArray: Section[] = resume.sections.map((item) => item.type);
sectionArray.push("custom");
sectionArray.push("final");
const sec = searchParams.get("sec");

if (sec && !validateSection(sec)) {
toast.error("Invalid section");
router.push(`/build-resume/${resumeId}/tips?sec=header`);
return null;
}

const currentSection = pathname.split("/section/")[1];
if (currentSection && !validateSection(currentSection)) {
toast.error("Invalid section");
router.push(`/build-resume/${resumeId}/tips?sec=header`);
return null;
}

const { prevUrl, nextUrl } = getNavigationUrls(sectionArray, sec, pathname);

// Render
return (
<>
<div className="flex flex-shrink-0 !z-[100000] bg-primary w-full md:hidden">
<VerticalTimeline />
</div>
<div className="relative pt-6 w-full px-4 flex md:hidden items-center justify-between">
<Button
onClick={()=>router.push('/build-resume/templates')}
variant={"outline"}
className=" cursor-pointer"
>
Home
</Button>
<MobilePreviewButton item={resume as ResumeTemplate} />
</div>
<div className="flex md:min-h-screen w-full">
<div className="flex flex-1 overflow-hidden">
<div className="w-[150px] bg-primary hidden md:flex flex-shrink-0">
<VerticalTimeline />
</div>

<div
className={cn(
"flex-grow overflow-x-hidden !z-[1] md:max-w-[80%] overflow-y-auto",
geologicaFont.className
)}
>
{children}
{(isMobile || (!currentSection && !isMobile)) && (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{
duration: 0.4,
delay: 0.8,
ease: [0, 0.71, 0.2, 1.01],
}}
className="flex mb-32 md:mb-0 flex-col md:flex-row w-full md:max-w-[90%] px-4 md:px-16 items-center mt-4 justify-between"
>
<ContineBtn path={prevUrl} text="Back" type="outline" />
<ContineBtn path={nextUrl} text="Continue" type="default" />
</motion.div>
)}
</div>
</div>

<div className="hidden md:flex w-[30vw]">
<LiveResumePreview />
</div>
</div>

<PreviewModal />
</>
);
};

export default ResumeBuilderLayout;
43 changes: 43 additions & 0 deletions app/(resume)/build-resume/[id]/(edit)/section/custom/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import CustomForm from "@/components/forms/CustomForm";
import SkillsForm from "@/components/forms/SkillsForm";
import HeaderSkeleton from "@/components/HeaderSkeleton";
import SectionInfo from "@/components/SectionInfo";
import { api } from "@/convex/_generated/api";
import { Doc, Id } from "@/convex/_generated/dataModel";
import { useQuery } from "convex/react";
import { useParams } from "next/navigation";
import { useRouter } from 'nextjs-toploader/app';

const Page = () => {
const params = useParams();
const resumeId = params.id;
const resume = useQuery(api.resume.getTemplateDetails, {
id: resumeId as Id<"resumes">,
});

if (resume === null) {
return <div>No Template Found</div>;
}
if (resume === undefined) {
return <HeaderSkeleton />;
}

return (
<div className="my-10 md:my-24 mx-4 md:mx-16">
<SectionInfo
heading="Create a Custom Section"
text="Use this space to elaborate on specific projects, certifications, or contributions that demonstrate your expertise if you want to."
/>

<CustomForm
resumeId={resumeId as Id<"resumes">}
styles={"sadf"}
item={"asdf"}
/>
</div>
);
};

export default Page;
Loading

0 comments on commit ad4f403

Please sign in to comment.