├── .eslintrc.json
├── .gitignore
├── README.md
├── actions
├── AddComments.ts
├── ChangePassword.ts
├── CheckUsernameAvailable.ts
├── CreateUserAccount.ts
├── DeleteBug.ts
├── DeleteComment.ts
├── DeleteFeed.ts
├── DeleteFeedComment.ts
├── DeleteMessage.ts
├── DeleteSnippet.ts
├── FeedLikesIncreaseOrDecrease.ts
├── GeminiResponse.ts
├── GetAllSnippets.ts
├── GetAllUsers.ts
├── GetBugs.ts
├── GetChat.ts
├── GetFeedComment.ts
├── GetFeedForPublicProfile.ts
├── GetLatestFeed.ts
├── GetLikesOfFeed.ts
├── GetOneFeed.ts
├── GetParticularUserPost.ts
├── GetPostForPublicProfile.ts
├── GetSinglePost.ts
├── GetUserChat.ts
├── GetUserDetails.ts
├── GetUserDetailsInProfile.ts
├── GetUsrDetailsForPublicProfile.ts
├── GetfeedByProfile.ts
├── LoginAction.ts
├── LogoutUser.ts
├── RunCode.ts
├── SaveAndSendMessage.ts
├── SaveEditedFeed.ts
├── SaveUserOtherData.ts
├── SendReview.ts
├── SentMailForForgotPassword.ts
├── SetCoverImage.ts
├── SetProfileImage.ts
├── UpdateBugStatus.ts
├── VerifyEmailForForgotPassword.ts
├── VerifyUserAtSignup.ts
├── saveCommentsforFeed.ts
├── saveFeedPost.ts
└── uploadSnippets.ts
├── components.json
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── prisma
├── index.ts
└── schema.prisma
├── public
└── linear.webp
├── src
├── app
│ ├── (CheckMessage)
│ │ └── MessageList
│ │ │ └── page.tsx
│ ├── (auth)
│ │ ├── _components
│ │ │ ├── ChangePassword.tsx
│ │ │ ├── ForgotPassword.tsx
│ │ │ ├── LeftSideSnippet.tsx
│ │ │ ├── OtpForSignup.tsx
│ │ │ └── VerifyEmail.tsx
│ │ ├── login
│ │ │ └── page.tsx
│ │ └── sign-up
│ │ │ └── page.tsx
│ ├── (home)
│ │ └── _components
│ │ │ ├── Card.tsx
│ │ │ ├── Footer.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── HeroScrollDemo.tsx
│ │ │ ├── Home.tsx
│ │ │ └── HoverEffect.tsx
│ ├── (private)
│ │ └── profile
│ │ │ ├── [username]
│ │ │ └── page.tsx
│ │ │ ├── _components
│ │ │ ├── CustomDialog.tsx
│ │ │ ├── CustomDialogProfileImage.tsx
│ │ │ └── DialogForOtherSection.tsx
│ │ │ └── page.tsx
│ ├── api
│ │ ├── ImageUpload
│ │ │ └── route.ts
│ │ ├── ImageUploadForLink
│ │ │ └── route.ts
│ │ ├── SaveBug
│ │ │ └── route.ts
│ │ ├── generate
│ │ │ └── route.ts
│ │ ├── pusher
│ │ │ └── auth
│ │ │ │ └── route.ts
│ │ └── test
│ │ │ └── route.ts
│ ├── askAi
│ │ └── page.tsx
│ ├── description
│ │ └── [id]
│ │ │ └── page.tsx
│ ├── explore
│ │ ├── _components
│ │ │ └── ExploreCards.tsx
│ │ ├── bugtracker
│ │ │ ├── _components
│ │ │ │ ├── Demo.tsx
│ │ │ │ ├── Kanban.tsx
│ │ │ │ └── constant.ts
│ │ │ ├── addBug
│ │ │ │ └── page.tsx
│ │ │ └── page.tsx
│ │ ├── code-editor
│ │ │ ├── _components
│ │ │ │ └── CustomEditor.tsx
│ │ │ └── page.tsx
│ │ ├── image-generator
│ │ │ └── page.tsx
│ │ ├── imageUpload
│ │ │ └── page.tsx
│ │ └── page.tsx
│ ├── favicon.ico
│ ├── feeds
│ │ ├── [feedId]
│ │ │ └── page.tsx
│ │ ├── _components
│ │ │ ├── Comment-Dialog.tsx
│ │ │ ├── Comment.tsx
│ │ │ └── HeaderImageCard.tsx
│ │ ├── page.tsx
│ │ └── uploadfeeds
│ │ │ └── page.tsx
│ ├── fonts
│ │ ├── GeistMonoVF.woff
│ │ └── GeistVF.woff
│ ├── globals.css
│ ├── layout.tsx
│ ├── not-found.tsx
│ ├── page.tsx
│ ├── reviewUs
│ │ └── page.tsx
│ ├── sendMsg
│ │ └── [username]
│ │ │ └── page.tsx
│ ├── snippets
│ │ ├── _components
│ │ │ └── CodeCard.tsx
│ │ └── page.tsx
│ ├── uploadSnippets
│ │ ├── _components
│ │ │ ├── CodeInput.tsx
│ │ │ ├── DescriptionForUpload.tsx
│ │ │ └── Searchlanguage.tsx
│ │ └── page.tsx
│ └── userChat
│ │ ├── _components
│ │ └── ChatCard.tsx
│ │ └── page.tsx
├── components
│ ├── BackgroundBeamsWithCollision.tsx
│ ├── Navbar.tsx
│ ├── NextUItheme.tsx
│ ├── Toggle
│ │ ├── MoonIcon.tsx
│ │ ├── SunIcon.tsx
│ │ └── Switch.tsx
│ ├── avatar.tsx
│ ├── card-hover-effect.tsx
│ ├── card.tsx
│ ├── container-scroll-animation.tsx
│ ├── separator.tsx
│ ├── text-generate-effect.tsx
│ └── ui
│ │ ├── 3d-card.tsx
│ │ ├── alert.tsx
│ │ ├── avatar.tsx
│ │ ├── badge.tsx
│ │ ├── button.tsx
│ │ ├── card.tsx
│ │ ├── checkbox.tsx
│ │ ├── dialog.tsx
│ │ ├── dropdown-menu.tsx
│ │ ├── file-upload.tsx
│ │ ├── input.tsx
│ │ ├── kanban.tsx
│ │ ├── label.tsx
│ │ ├── popover.tsx
│ │ ├── scroll-area.tsx
│ │ ├── select.tsx
│ │ ├── switch.tsx
│ │ ├── textarea.tsx
│ │ ├── toast.tsx
│ │ └── toaster.tsx
├── helpers
│ ├── SendEmail.js
│ ├── SendIt.ts
│ └── VerificationEmail.jsx
├── hooks
│ └── use-toast.ts
├── lib
│ ├── LanguageData.ts
│ ├── cloudinary.ts
│ ├── cloudinaryImageUploader.ts
│ ├── constants.ts
│ ├── pusher
│ │ ├── client
│ │ │ └── index.ts
│ │ └── server
│ │ │ └── index.ts
│ └── utils.ts
├── middleware.ts
└── types
│ ├── ChangePasswordTypes.ts
│ ├── LoginTypes.ts
│ ├── SignupTypes.ts
│ └── forgotPasswordTypes.ts
├── tailwind.config.ts
└── tsconfig.json
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["next/core-web-vitals", "next/typescript"],
3 | "rules": {
4 | "@typescript-eslint/no-explicit-any": "off",
5 | "@typescript-eslint/no-unused-vars": "off",
6 | "@typescript-eslint/no-unused-expressions": "off"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | .env
10 |
11 | # testing
12 | /coverage
13 |
14 | # next.js
15 | /.next/
16 | /out/
17 |
18 | # production
19 | /build
20 |
21 | # misc
22 | .DS_Store
23 | *.pem
24 |
25 | # debug
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 |
30 | # local env files
31 | .env*.local
32 |
33 | # vercel
34 | .vercel
35 |
36 | # typescript
37 | *.tsbuildinfo
38 | next-env.d.ts
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Snippets
2 |
3 | A prototype project for making snippets app in which various code snippets are there, AI for solving issues, in progress we will make this SAAS project in NextJs
4 |
5 | # React + TypeScript + Vite
6 |
7 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
8 |
9 | Currently, two official plugins are available:
10 |
11 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
12 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
13 |
14 |
15 | [](https://postimg.cc/MXcjgfFY)
16 |
17 | [](https://postimg.cc/8JLgrHCH)
18 |
19 | [](https://postimg.cc/yWPYQ1VT)
20 |
21 |
--------------------------------------------------------------------------------
/actions/AddComments.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { cookies } from "next/headers";
3 | import { revalidatePath } from "next/cache";
4 | import jwt, { JwtPayload } from "jsonwebtoken";
5 | import prisma from "../prisma";
6 | interface CommentsData {
7 | postId: string,
8 | content: string
9 | }
10 |
11 | export async function AddComments(data: CommentsData) {
12 | try {
13 | revalidatePath("/description");
14 | const cookieStore = cookies();
15 | const getToken = cookieStore.get("snippets")?.value as string;
16 | const userDetails = jwt.verify(getToken, process.env.JWT_SECRET!) as JwtPayload;
17 |
18 | if (!userDetails) {
19 | return { msg: "User not found", status: false };
20 | }
21 |
22 | const saveComment = await prisma.comment.create({
23 | data: {
24 | content: data.content,
25 | postId: data.postId,
26 | authorId: userDetails.id
27 | }
28 | })
29 |
30 |
31 | const allComment = await prisma.postSnippet.findFirst({
32 | where: {
33 | id: data.postId, // Ensure 'id' is defined and valid
34 | },
35 | include: {
36 | author: { // Including the author's details
37 | select: {
38 | name: true,
39 | id: true
40 | },
41 | },
42 | comments: { // Including comments and their related author
43 | include: {
44 | author: { // Include the author of the comment
45 | select: {
46 | name: true,
47 | id: true
48 | }
49 | }
50 | }
51 | }
52 | },
53 | });
54 | return { msg: "Get the comments", data: allComment, status: true };
55 | } catch (error) {
56 | return { msg: "Internal Server error", status: false };
57 | }
58 | }
--------------------------------------------------------------------------------
/actions/ChangePassword.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import prisma from "../prisma";
4 | import bcrypt from "bcryptjs";
5 |
6 | export async function ChangePasswordActions(data: any) {
7 | revalidatePath("/login");
8 | if (!data || !data.confirmPassword || !data.password || !data.email) {
9 | return { msg: "Fields are empty", status: false }
10 | }
11 | try {
12 | const findEmail = await prisma.user.findFirst({
13 | where: {
14 | email: data.email
15 | }
16 | })
17 |
18 | if (!findEmail) {
19 | return { msg: "wrong Credentials", status: false }
20 | }
21 |
22 | const hashedPassword = await bcrypt.hash(data.password, 10);
23 |
24 | await prisma.user.update({
25 | where: {
26 | id: findEmail.id
27 | },
28 | data: {
29 | password: hashedPassword
30 | }
31 | })
32 |
33 | return { msg: "Credentials updated successfully", status: true }
34 | } catch (error) {
35 | return { msg: "Internal Server error", status: false };
36 | }
37 | }
--------------------------------------------------------------------------------
/actions/CheckUsernameAvailable.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import prisma from "../prisma";
4 |
5 | export async function CheckUsernameUnique(username: string) {
6 | revalidatePath("/sign-up");
7 | try {
8 | // console.log(username)
9 | const findUserName = await prisma.user.findFirst({
10 | where: {
11 | username: username
12 | }
13 | })
14 |
15 | if (findUserName) {
16 | return { message: "Username already exist", status: false }
17 | }
18 |
19 | return { message: "Username is available", status: true }
20 | } catch (error) {
21 | return { message: "Internal Server error", status: false }
22 | }
23 | }
--------------------------------------------------------------------------------
/actions/CreateUserAccount.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { signUpTypes } from "@/types/SignupTypes";
4 | import prisma from "../prisma";
5 | import Sendit from "@/helpers/SendIt";
6 | import bcrypt from "bcryptjs";
7 |
8 | export async function CreateUserAccount(data: signUpTypes) {
9 | // console.log(data);
10 |
11 | try {
12 | const findUser = await prisma.user.findFirst({
13 | where:
14 | {
15 | OR: [
16 | {
17 | email: data.email
18 | },
19 | {
20 | username: data.username
21 | }
22 | ]
23 | }
24 | })
25 |
26 | if (findUser) {
27 | return { msg: "Username already exist", status: false }
28 | }
29 |
30 | const randomNumber = Math.floor(1000 + Math.random() * 9000).toString();
31 | const hashedPassword = await bcrypt.hash(data.password, 10);
32 | const createUser = await prisma.user.create({
33 | data: {
34 | name: data.name,
35 | username: data.username,
36 | email: data.email,
37 | password: hashedPassword,
38 | verificationOtp: randomNumber
39 | }
40 | })
41 |
42 | // console.log(createUser);
43 |
44 |
45 | await Sendit({to: data.email, name: data.name, subject: "Email Verification", body: randomNumber})
46 |
47 | return { msg: "User created successfully", status: true }
48 | } catch (error) {
49 | return { msg: "Internal Server error", status: false };
50 | }
51 | }
--------------------------------------------------------------------------------
/actions/DeleteBug.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import prisma from "../prisma";
4 | import { GetUserDetails } from "./GetUserDetails";
5 |
6 | export async function DeleteBug(id: string) {
7 | try {
8 | const getUser = await GetUserDetails();
9 | console.log(id);
10 |
11 | if (!getUser || !getUser.decodeCookieValue || !getUser.decodeCookieValue.id) {
12 | return { msg: "Unauthorized access denied", status: false };
13 | }
14 |
15 | await prisma.bugTracker.delete({
16 | where: {
17 | id
18 | }
19 | })
20 |
21 | // console.log(deleteBug);
22 | return { msg: "successfully deleted the task", status: true };
23 | } catch (error) {
24 | return { msg: "Internal Server error", status: false };
25 | }
26 | }
--------------------------------------------------------------------------------
/actions/DeleteComment.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | interface DataTypes {
7 | commentId: string;
8 | postId: string
9 | }
10 |
11 | export async function DeleteComment(data: DataTypes) {
12 | revalidatePath("/description");
13 | const { commentId, postId } = data;
14 | try {
15 | await prisma.comment.delete({
16 | where: {
17 | id: commentId
18 | }
19 | })
20 |
21 | const getPost = await prisma.postSnippet.findFirst({
22 | where: {
23 | id: postId,
24 | },
25 | include: {
26 | author: {
27 | select: {
28 | name: true,
29 | id: true,
30 | username: true
31 | },
32 | },
33 | comments: {
34 | include: {
35 | author: {
36 | select: {
37 | name: true,
38 | id: true,
39 | username: true
40 | }
41 | }
42 | }
43 | }
44 | },
45 | });
46 |
47 | return { msg: "Comment deleted successfully", data: getPost, status: true }
48 | } catch (error) {
49 | return { msg: "Internal Server error", status: false }
50 | }
51 | }
--------------------------------------------------------------------------------
/actions/DeleteFeed.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 | import { Redis } from "@upstash/redis";
6 |
7 | const redis = Redis.fromEnv();
8 | export async function DeleteFeed(feedId: string) {
9 | revalidatePath("/feeds");
10 | try {
11 | const deleteFeed = await prisma.feeds.delete({
12 | where: {
13 | id: feedId
14 | }
15 | })
16 |
17 | await redis.del("latestfeed");
18 | return { msg: "Successfully deleted the feed", status: true };
19 | } catch (error) {
20 | return { msg: "Internal Server error", status: false };
21 | }
22 | }
--------------------------------------------------------------------------------
/actions/DeleteFeedComment.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | export async function DeleteFeedComment(commentId: string) {
7 | revalidatePath("/feeds");
8 |
9 | try {
10 | const deleteComment = await prisma.feedsComment.delete({
11 | where: {
12 | id: commentId
13 | }
14 | })
15 | console.log(deleteComment)
16 | return { msg: "Comment deleted successfully", status: true };
17 | } catch (error) {
18 | return { msg: "Internal Server error", status: false };
19 | }
20 | }
--------------------------------------------------------------------------------
/actions/DeleteMessage.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | export async function DeleteMessage(id: string) {
7 | revalidatePath("/userChat");
8 | try {
9 | await prisma.chat.delete({
10 | where: {
11 | id
12 | }
13 | })
14 |
15 | return { msg: "Message Deleted Successfully", status: true };
16 | } catch (error) {
17 | return { msg: "Internal Server error", status: false };
18 | }
19 | }
--------------------------------------------------------------------------------
/actions/DeleteSnippet.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 | import { GetUserDetails } from "./GetUserDetails";
6 |
7 | export async function DeleteSnippet(id: any) {
8 | revalidatePath("/snippets");
9 | try {
10 | const getUserDetails = await GetUserDetails();
11 |
12 | if (!getUserDetails) {
13 | return { msg: "Unauthorized access denied", status: false }
14 | }
15 |
16 |
17 | await prisma.postSnippet.delete({
18 | where: {
19 | id: id
20 | }
21 | })
22 |
23 | return { msg: "Post Deleted Successfully", status: true }
24 | } catch (error) {
25 | return { msg: "Internal Server error", status: false }
26 | }
27 | }
--------------------------------------------------------------------------------
/actions/FeedLikesIncreaseOrDecrease.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 |
7 | export async function FeedLikesIncreaseorDecrease(feedId: string) {
8 | revalidatePath("/feeds");
9 | try {
10 |
11 | // console.log("Feed id is: ", feedId);
12 | const userDetails = await GetUserDetails();
13 |
14 | if (!userDetails || !userDetails.decodeCookieValue) {
15 | return { msg: "Unauthorized access denied", status: false };
16 | }
17 |
18 | const findUserInLikeFeed = await prisma.feedsLikes.findFirst({
19 | where: {
20 | AND: [
21 | { authorId: userDetails.decodeCookieValue?.id },
22 | { feedId: feedId }
23 | ]
24 | }
25 | });
26 | // console.log(findUserInLikeFeed);
27 |
28 | if (!findUserInLikeFeed) {
29 | const likeTheFeed = await prisma.feedsLikes.create({
30 | data: {
31 | feedId: feedId,
32 | authorId: userDetails.decodeCookieValue.id
33 | }
34 | })
35 | }
36 | else {
37 | const removeLikeFeed = await prisma.feedsLikes.deleteMany({
38 | where: {
39 | authorId: userDetails.decodeCookieValue?.id,
40 | feedId: feedId
41 | }
42 | })
43 | }
44 |
45 | const getAllLikes = await prisma.feedsLikes.findMany({
46 | where: {
47 | feedId: feedId
48 | }
49 | });
50 | const data = {
51 | userId: userDetails.decodeCookieValue.id,
52 | likesCount: getAllLikes.length,
53 | getAllLikes
54 | }
55 |
56 | // console.log(data);
57 |
58 | return { msg: "Liked Successfully", data, status: true };
59 | } catch (error) {
60 | return { msg: "Internal Server error", status: false };
61 | }
62 | }
--------------------------------------------------------------------------------
/actions/GeminiResponse.ts:
--------------------------------------------------------------------------------
1 | 'use server'
2 |
3 | import { GoogleGenerativeAI } from "@google/generative-ai";
4 |
5 | // Initialize the Google AI client
6 | const googleAI = new GoogleGenerativeAI(process.env.GOOGLE_GEMINI_API_KEY!);
7 | const geminiModel = googleAI.getGenerativeModel({
8 | model: "gemini-1.5-flash",
9 | });
10 |
11 | // Helper function to generate content
12 | const generate = async (question: string) => {
13 | try {
14 | const result = await geminiModel.generateContent(question);
15 | const response = await result.response.text();
16 | return response;
17 | } catch (error: any) {
18 | console.error("Error generating content from AI:", error.message);
19 | throw new Error("Failed to generate AI content");
20 | }
21 | };
22 |
23 | // Server Action
24 | export async function askAI(data: any) {
25 | try {
26 | // Get the question from formData if using with a form
27 | const { question } = data;
28 |
29 | if (!question || typeof question !== 'string') {
30 | throw new Error("Invalid or missing question");
31 | }
32 |
33 | // Generate the response
34 | const result = await generate(question);
35 |
36 | if (!result) {
37 | throw new Error("No content generated from the AI");
38 | }
39 |
40 | // Return successful response
41 | return {
42 | data: result,
43 | error: null,
44 | status: true
45 | };
46 |
47 | } catch (error) {
48 | console.error("askAI error:", error);
49 |
50 | // Return error response
51 | return {
52 | data: null,
53 | error: "An error occurred while processing your request",
54 | status: false
55 | };
56 | }
57 | }
--------------------------------------------------------------------------------
/actions/GetAllSnippets.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | export async function GetAllSnippets() {
7 | revalidatePath("/snippets");
8 |
9 | try {
10 | const getAllSnippets = await prisma.postSnippet.findMany();
11 |
12 | return {msg: "Fetched all snippets", status: true, data: getAllSnippets};
13 | } catch (error) {
14 | return { msg: "Internal Server error", status: false };
15 | }
16 | }
--------------------------------------------------------------------------------
/actions/GetAllUsers.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import prisma from "../prisma";
4 | import { GetUserDetails } from "./GetUserDetails";
5 |
6 | export async function GetAllUser() {
7 | revalidatePath("/MessageList");
8 |
9 | try {
10 | const getUserDetails = (await GetUserDetails()).decodeCookieValue;
11 | const userFriends = await prisma.friends.findMany({
12 | where: {
13 | userId: getUserDetails?.id,
14 | },
15 | include: {
16 | friend: {
17 | select: {
18 | id: true, // Fetch the id of the friend
19 | username: true,
20 | profileImage: true // Fetch the username of the friend
21 | }
22 | }
23 | }
24 | });
25 |
26 | // console.log(userFriends)
27 | return { msg: "Successfully get All users", data: userFriends, status: false };
28 | } catch (error) {
29 | return { msg: "Internal Server error", status: false };
30 | }
31 | }
--------------------------------------------------------------------------------
/actions/GetBugs.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 |
7 | export async function GetBugs() {
8 | revalidatePath("/explore/bugtracker");
9 |
10 | try {
11 | const getUser = await GetUserDetails();
12 |
13 | if (!getUser || !getUser.decodeCookieValue || !getUser.decodeCookieValue.id) {
14 | return { msg: "Unauthorized access", status: false };
15 | }
16 |
17 | const getAllBugs = await prisma.bugTracker.findMany({
18 | where: {
19 | userId: getUser.decodeCookieValue.id
20 | }
21 | })
22 |
23 | return { msg: "Successfully got all the bugs", data: getAllBugs, status: true };
24 | } catch (error) {
25 | return { msg: "Internal Server error", status: false };
26 | }
27 | }
--------------------------------------------------------------------------------
/actions/GetChat.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 |
7 | export async function GetChat(selectedUserId: string) {
8 | revalidatePath("/");
9 | try {
10 | const getUserDetails = await GetUserDetails();
11 | console.log("Sender: ", getUserDetails?.decodeCookieValue?.id);
12 | console.log("Receiver: ", selectedUserId)
13 | const ChatBetweenThem = await prisma.chat.findMany({
14 | where: {
15 | OR: [
16 | {
17 | senderId: getUserDetails?.decodeCookieValue?.id,
18 | receiverId: selectedUserId,
19 | },
20 | {
21 | senderId: selectedUserId,
22 | receiverId: getUserDetails?.decodeCookieValue?.id,
23 | },
24 | ],
25 | },
26 | orderBy: {
27 | createdAt: 'asc', // Order messages by timestamp (ascending)
28 | },
29 |
30 | select: {
31 | text: true,
32 | senderId: true,
33 | createdAt: true
34 | }
35 | })
36 |
37 | return { msg: "Get the chats", chat: ChatBetweenThem, status: true };
38 | } catch (error) {
39 | console.log(error);
40 | return { msg: "Internal Server error", status: false };
41 | }
42 | }
--------------------------------------------------------------------------------
/actions/GetFeedComment.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | export async function GetFeedComment(feedId: string) {
7 | revalidatePath("/feeds");
8 | try {
9 | const getAllComments = await prisma.feedsComment.findMany({
10 | where: {
11 | feedId
12 | },
13 | include: {
14 | author: {
15 | select: {
16 | id: true,
17 | username: true,
18 | profileImage: true
19 | }
20 | },
21 | feed: {
22 | select: {
23 | authorId: true
24 | }
25 | }
26 | },
27 | orderBy: {
28 | createdAt: 'desc'
29 | },
30 | })
31 |
32 | console.log(getAllComments)
33 | return {msg: "Successfully get alll the comments", commentsData: getAllComments, status: true}
34 | } catch (error) {
35 | return { msg: "Internal Server error", status: false };
36 | }
37 | }
--------------------------------------------------------------------------------
/actions/GetFeedForPublicProfile.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 |
7 | export async function GetFeedForPublicProfile(username: string){
8 | revalidatePath("/feeds");
9 | try {
10 | const userDetails = await prisma.user.findFirst({
11 | where: {
12 | username: username
13 | }
14 | });
15 | if(!userDetails){
16 | return { msg: "Failed to get the Feeds", status: false };
17 | }
18 |
19 | const getFeeds = await prisma.feeds.findMany({
20 | where: {
21 | authorId: userDetails?.id
22 | },
23 | include: {
24 | author: {
25 | select: {
26 | name: true,
27 | username: true,
28 | id: true,
29 | profileImage: true
30 | },
31 | },
32 | },
33 | orderBy: {
34 | createdAt: "desc"
35 | }
36 | })
37 | // console.log(getFeeds);
38 | return { msg: "Successfully got the feed", feedsData: getFeeds ,status: true };
39 | } catch (error) {
40 | return { msg: "Internal Server error", status: false };
41 | }
42 | }
--------------------------------------------------------------------------------
/actions/GetLatestFeed.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 | import { Redis } from "@upstash/redis";
7 |
8 | const redis = Redis.fromEnv();
9 | export async function GetLatestFeed() {
10 | revalidatePath("/feeds");
11 | try {
12 | const userDetails = await GetUserDetails();
13 | if (!userDetails) {
14 | return { msg: "Failed to get the Feeds", status: false };
15 | }
16 |
17 | const cachedValues = await redis.get("latestfeed");
18 |
19 | if (cachedValues) {
20 | return { msg: "Successfully got the feed", feedsData: cachedValues, status: true };
21 | }
22 |
23 | const getFeeds = await prisma.feeds.findMany({
24 | include: {
25 | author: {
26 | select: {
27 | name: true,
28 | username: true,
29 | id: true,
30 | profileImage: true
31 | },
32 | },
33 | },
34 | orderBy: {
35 | createdAt: "desc"
36 | }
37 | })
38 |
39 | await redis.set("latestfeed", getFeeds);
40 | await redis.expire("latestfeed", 120);
41 |
42 | return { msg: "Successfully got the feed", feedsData: getFeeds, status: true };
43 | } catch (error) {
44 | return { msg: "Internal Server error", status: false };
45 | }
46 | }
--------------------------------------------------------------------------------
/actions/GetLikesOfFeed.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 |
7 | export async function GetLikesOfFeed(feedId: string) {
8 | revalidatePath("/feeds");
9 |
10 | try {
11 | const userDetails = await GetUserDetails();
12 |
13 | if (!userDetails || !userDetails.decodeCookieValue) {
14 | return { msg: "Unauthorized access denied", status: false };
15 | }
16 | console.log(feedId)
17 | const getAllLikes = await prisma.feedsLikes.findMany({
18 | where: {
19 | feedId: feedId
20 | }
21 | });
22 | const data = {
23 | userId: userDetails.decodeCookieValue.id,
24 | likesCount: getAllLikes.length,
25 | getAllLikes
26 | }
27 |
28 | return { msg: "Liked Successfully", data, status: true };
29 | } catch (error) {
30 | return { msg: "Internal Server error", status: false };
31 | }
32 | }
--------------------------------------------------------------------------------
/actions/GetOneFeed.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import { GetUserDetails } from "./GetUserDetails";
4 | import prisma from "../prisma";
5 |
6 | export async function GetOneFeed(feedId: string) {
7 | revalidatePath("/feeds");
8 |
9 | try {
10 | const userDetails = await GetUserDetails();
11 | if (!userDetails) {
12 | return { msg: "Failed to get the Feeds", status: false };
13 | }
14 |
15 | const getOneFeed = await prisma.feeds.findUnique({
16 | where: {
17 | id: feedId
18 | },
19 |
20 | include: {
21 | author: {
22 | select: {
23 | name: true,
24 | username: true,
25 | id: true,
26 | profileImage: true
27 | },
28 | },
29 | },
30 | })
31 | console.log(getOneFeed)
32 | return {msg: "Successfully got the feed", data: getOneFeed, status: true};
33 | } catch (error) {
34 | return { msg: "Internal Server error", status: false };
35 | }
36 | }
--------------------------------------------------------------------------------
/actions/GetParticularUserPost.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import prisma from "../prisma";
4 | import { GetUserDetails } from "./GetUserDetails";
5 |
6 | export async function GetPostForProfile(){
7 | revalidatePath("/profile");
8 | try {
9 | const userDetails = await GetUserDetails();
10 | if(!userDetails){
11 | return { msg: "User not found", status: false };
12 | }
13 |
14 | const getAllSnippets = await prisma.postSnippet.findMany({
15 | where: {
16 | authorId: userDetails.decodeCookieValue?.id
17 | }
18 | });
19 |
20 | // console.log(getAllSnippets)
21 | return {msg: "Fetched all snippets", status: true, data: getAllSnippets};
22 | } catch (error) {
23 | return { msg: "Internal Server error", status: false };
24 | }
25 | }
--------------------------------------------------------------------------------
/actions/GetPostForPublicProfile.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import prisma from "../prisma";
4 |
5 | export async function GetPostForPublicProfile(username: string) {
6 | revalidatePath("/profile");
7 | try {
8 | const authorId = await prisma.user.findFirst({
9 | where: {
10 | username
11 | }
12 | })
13 |
14 |
15 | if(!authorId){
16 | return { msg: "User not found", status: false };
17 | }
18 | const findUser = await prisma.postSnippet.findMany({
19 | where: {
20 | authorId: authorId.id
21 | }
22 | })
23 |
24 | if (!findUser) {
25 | return { msg: "User not found", status: false };
26 | }
27 |
28 | return { msg: "Get User successfully", data: findUser, status: true };
29 |
30 | } catch (error) {
31 | return { msg: "Internal Server error", status: false };
32 | }
33 | }
--------------------------------------------------------------------------------
/actions/GetSinglePost.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 | import { string } from "zod";
6 |
7 | export async function GetSinglePost(id: string) {
8 | revalidatePath("/description");
9 | try {
10 | const getPost = await prisma.postSnippet.findFirst({
11 | where: {
12 | id: id,
13 | },
14 | include: {
15 | author: {
16 | select: {
17 | name: true,
18 | id: true,
19 | username: true
20 | },
21 | },
22 | comments: {
23 | include: {
24 | author: {
25 | select: {
26 | name: true,
27 | id: true,
28 | username: true
29 | }
30 | }
31 | }
32 | }
33 | },
34 | });
35 |
36 | // console.log(getPost);
37 | return { msg: "Succeed to get The post", data: getPost, status: true }
38 | } catch (error) {
39 | return { msg: "Internal Server error", status: false }
40 | }
41 | }
--------------------------------------------------------------------------------
/actions/GetUserChat.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 | import { GetUserDetails } from "./GetUserDetails";
6 |
7 | export async function GetUserChat() {
8 | revalidatePath("/userChat");
9 | try {
10 | const getUserDetails = await GetUserDetails();
11 | if (!getUserDetails.decodeCookieValue) {
12 | return { msg: "Something went wrong", status: false };
13 | }
14 |
15 | const getUserChat = await prisma.chat.findMany({
16 | where: {
17 | receiverId: getUserDetails.decodeCookieValue.id
18 | },
19 | select: {
20 | id: true,
21 | text: true,
22 | sender: {
23 | select: {
24 | username: true,
25 | profileImage: true
26 | }
27 | },
28 | receiverId: true,
29 | createdAt: true,
30 | updatedAt: true,
31 | }
32 | })
33 |
34 | if (!getUserChat) {
35 | return { msg: "Failed to get messages, Please try again", status: false };
36 | }
37 | // console.log(getUserChat)
38 | return { msg: "Successfully get the Chat", getUserChat, status: true };
39 | } catch (error) {
40 | return { msg: "Internal Server error", status: false };
41 | }
42 | }
--------------------------------------------------------------------------------
/actions/GetUserDetails.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { cookies } from "next/headers";
5 | import jwt, { JwtPayload } from "jsonwebtoken";
6 |
7 | export async function GetUserDetails(){
8 | revalidatePath("/");
9 |
10 | try {
11 | const cookieStore = cookies();
12 |
13 | const getCookie = cookieStore.get("snippets")?.value as string;
14 | const decodeCookieValue = jwt.verify(getCookie, process.env.JWT_SECRET!) as JwtPayload;
15 |
16 | return { msg: "Get the user details", decodeCookieValue, status: true };
17 | } catch (error) {
18 | return { msg: "Internal Server error", status: false };
19 | }
20 | }
--------------------------------------------------------------------------------
/actions/GetUserDetailsInProfile.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { cookies } from "next/headers";
5 | import jwt, { JwtPayload } from "jsonwebtoken";
6 | import prisma from "../prisma";
7 |
8 | export async function GetUserDetailsInProfile(){
9 | revalidatePath("/profile");
10 |
11 | try {
12 | const cookieStore = cookies();
13 |
14 | const getCookie = cookieStore.get("snippets")?.value as string;
15 | const decodeCookieValue = jwt.verify(getCookie, process.env.JWT_SECRET!) as JwtPayload;
16 |
17 | const findUser = await prisma.user.findFirst({
18 | where: {
19 | id: decodeCookieValue.id
20 | }
21 | })
22 |
23 | return { msg: "Get the user details", decodeCookieValue: findUser, status: true };
24 | } catch (error) {
25 | return { msg: "Internal Server error", status: false };
26 | }
27 | }
--------------------------------------------------------------------------------
/actions/GetUsrDetailsForPublicProfile.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | export async function GetDetailsForPublicProfile(username: string) {
7 | revalidatePath("/profile");
8 | try {
9 | const findUser = await prisma.user.findFirst({
10 | where: {
11 | username
12 | }
13 | })
14 |
15 | if(!findUser){
16 | return {msg: "User not found", status: false};
17 | }
18 |
19 | return {msg: "Get User successfully", decodeCookieValue: findUser, status: true};
20 | } catch (error) {
21 | return { msg: "Internal Server error", status: false };
22 | }
23 | }
--------------------------------------------------------------------------------
/actions/GetfeedByProfile.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 |
7 | export async function GetFeedByProfile(){
8 | revalidatePath("/feeds");
9 | try {
10 | const userDetails = await GetUserDetails();
11 | if(!userDetails){
12 | return { msg: "Failed to get the Feeds", status: false };
13 | }
14 |
15 | const getFeeds = await prisma.feeds.findMany({
16 | where: {
17 | authorId: userDetails?.decodeCookieValue?.id
18 | },
19 | include: {
20 | author: {
21 | select: {
22 | name: true,
23 | username: true,
24 | id: true,
25 | profileImage: true
26 | },
27 | },
28 | },
29 | orderBy: {
30 | createdAt: "desc"
31 | }
32 | })
33 | // console.log(getFeeds);
34 | return { msg: "Successfully got the feed", feedsData: getFeeds ,status: true };
35 | } catch (error) {
36 | return { msg: "Internal Server error", status: false };
37 | }
38 | }
--------------------------------------------------------------------------------
/actions/LoginAction.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import prisma from "../prisma";
3 | import bcrypt from "bcryptjs";
4 | import jwt from "jsonwebtoken";
5 | import { cookies } from "next/headers";
6 |
7 | export async function LoginUser(data: any) {
8 | if (!data || !data.password) {
9 | return { msg: "fields are empty", status: false };
10 | }
11 |
12 | try {
13 | const findUser = await prisma.user.findFirst({
14 | where: {
15 | OR: [
16 | {
17 | email: data.username
18 | },
19 | {
20 | username: data.username
21 | }
22 | ]
23 | }
24 | })
25 |
26 | if (!findUser) {
27 | return { msg: "Wrong Credentials", status: false };
28 | }
29 |
30 | const comparePassword = await bcrypt.compare(data.password, findUser.password);
31 | if (!comparePassword) {
32 | return { msg: "Wrong Credentials", status: false };
33 | }
34 |
35 |
36 | let token = jwt.sign({
37 | id: findUser.id, name: findUser.name, email: findUser.email, verified: findUser.verified, username: findUser.username
38 | }, process.env.JWT_SECRET!, { expiresIn: '10d' });
39 |
40 | const cookieStore = cookies();
41 | const cookie = cookieStore.set('snippets', token, { httpOnly: true, sameSite: 'lax', expires: new Date(Date.now() + 10 * 24 * 60 * 60 * 1000) });
42 |
43 |
44 | return { msg: "Login successful", status: true };
45 | } catch (error) {
46 | return { msg: "Internal Server error", status: false };
47 | }
48 | }
--------------------------------------------------------------------------------
/actions/LogoutUser.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { cookies } from "next/headers";
5 |
6 | export async function LogoutUser(){
7 | revalidatePath("/profile");
8 | const cookieStore = cookies();
9 | cookieStore.delete("snippets");
10 | }
--------------------------------------------------------------------------------
/actions/RunCode.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { LANGUAGE_VERSIONS } from "@/lib/constants";
4 | import axios from "axios";
5 | import { revalidatePath } from "next/cache";
6 |
7 | const API = axios.create({
8 | baseURL: "https://emkc.org/api/v2/piston",
9 | });
10 |
11 | export const executeCode = async ({
12 | language,
13 | sourceCode
14 | }: {
15 | language: keyof typeof LANGUAGE_VERSIONS;
16 | sourceCode: string;
17 | }) => {
18 | try {
19 | revalidatePath("/explore/code-editor");
20 |
21 | const response = await API.post("/execute", {
22 | language: language,
23 | version: LANGUAGE_VERSIONS[language],
24 | files: [
25 | {
26 | content: sourceCode,
27 | },
28 | ],
29 | });
30 |
31 | return response.data;
32 | } catch (error) {
33 | console.error("Error executing code:", error);
34 | throw new Error("Failed to execute code. Please try again.");
35 | }
36 | };
--------------------------------------------------------------------------------
/actions/SaveAndSendMessage.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import prisma from "../prisma";
4 | import { GetUserDetails } from "./GetUserDetails";
5 |
6 | interface MessageData {
7 | receiverUsername: string;
8 | text: string;
9 | }
10 |
11 | export async function SaveAndSendMessage(data: MessageData) {
12 | try {
13 | const { text, receiverUsername } = data;
14 | if (!text || !receiverUsername) {
15 | return { msg: "Required Fields are Empty", status: false };
16 | }
17 |
18 | const getUserDetails = (await GetUserDetails()).decodeCookieValue;
19 | const findUser = await prisma.user.findFirst({
20 | where: {
21 | username: receiverUsername,
22 | },
23 | });
24 |
25 | if (!findUser) {
26 | return { msg: "User not found", status: false };
27 | }
28 |
29 | // Check if the users are already friends
30 | const existingFriendship = await prisma.friends.findFirst({
31 | where: {
32 | OR: [
33 | { userId: getUserDetails?.id, friendId: findUser.id },
34 | { userId: findUser.id, friendId: getUserDetails?.id },
35 | ],
36 | },
37 | });
38 |
39 | if (!existingFriendship) {
40 | // If no friendship exists, create two records for the friendship
41 | const saveUser = await prisma.friends.create({
42 | data: {
43 | userId: getUserDetails?.id, // The current user is creating the friendship
44 | friendId: findUser.id, // The user they are sending a message to
45 | },
46 | });
47 |
48 | const saveUser2 = await prisma.friends.create({
49 | data: {
50 | userId: findUser.id, // The recipient user is creating the friendship
51 | friendId: getUserDetails?.id, // The current user is their friend
52 | },
53 | });
54 | console.log(saveUser, saveUser2)
55 | }
56 |
57 | // Send the message
58 | await prisma.chat.create({
59 | data: {
60 | text: text,
61 | senderId: getUserDetails?.id,
62 | receiverId: findUser?.id,
63 | },
64 | });
65 |
66 | return { msg: "Message Sent Successfully", status: true };
67 | } catch (error) {
68 | console.error(error);
69 | return { msg: "Internal Server error", status: false };
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/actions/SaveEditedFeed.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | export async function SaveEditedFeed(feedText: string, feedId: string){
7 | revalidatePath("/feeds");
8 | try {
9 | const updatedFeedText = await prisma.feeds.update({
10 | where: {
11 | id: feedId
12 | },
13 | data: {
14 | content: feedText
15 | }
16 | })
17 |
18 | return {msg: "Successfully saved the updated feed", status: true};
19 | } catch (error) {
20 | return {msg: "Internal Server error", status: false};
21 | }
22 | }
--------------------------------------------------------------------------------
/actions/SaveUserOtherData.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import { cookies } from "next/headers";
4 | import jwt, { JwtPayload } from "jsonwebtoken";
5 | import prisma from "../prisma";
6 |
7 | interface DataTypes {
8 | workplace: string;
9 | about: string;
10 | location: string;
11 | badges: string[];
12 | }
13 |
14 |
15 | export async function SaveUserOtherData(data: DataTypes) {
16 | try {
17 | revalidatePath("/profile");
18 | const { workplace, about, location, badges } = data;
19 | // console.log(data);
20 | const cookieStore = cookies();
21 | const getCookie = cookieStore.get("snippets")?.value as string;
22 | const decodeCookieValue = jwt.verify(getCookie, process.env.JWT_SECRET!) as JwtPayload;
23 |
24 |
25 | const userOtherInfo: any = {};
26 |
27 | if (workplace?.length > 1) userOtherInfo.workplace = workplace;
28 | if (about?.length > 1) userOtherInfo.about = about;
29 | if (badges?.length > 1) userOtherInfo.badges = badges;
30 | if (location?.length > 1) userOtherInfo.location = location;
31 |
32 | const saveUserOtherData = await prisma.user.update({
33 | where: {
34 | id: decodeCookieValue.id
35 | },
36 | data: userOtherInfo
37 | });
38 |
39 | // console.log(saveUserOtherData);
40 | let token = jwt.sign(
41 | {
42 | id: saveUserOtherData.id,
43 | name: saveUserOtherData.name,
44 | email: saveUserOtherData.email,
45 | verified: saveUserOtherData.verified,
46 | },
47 | process.env.JWT_SECRET!,
48 | { expiresIn: '10d' }
49 | );
50 |
51 | cookieStore.set('snippets', token, { httpOnly: true, sameSite: 'lax', expires: new Date(Date.now() + 10 * 24 * 60 * 60 * 1000) });
52 |
53 | return { msg: "Data Saved Successfully", saveUserOtherData, status: true };
54 | } catch (error) {
55 | return { msg: "Internal Server Error", status: false };
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/actions/SendReview.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import Sendit from "@/helpers/SendIt";
4 | import { revalidatePath } from "next/cache";
5 |
6 | interface DataTypes{
7 | email: string;
8 | message: string;
9 | }
10 | export async function SendReview(data: DataTypes) {
11 | revalidatePath("/reviewUs");
12 | try {
13 | const {email, message } = data;
14 |
15 | if(!email || !message){
16 | return { msg: "Some Fields are empty", status: false };
17 | }
18 |
19 | await Sendit({to: "utkarshsingh132002@gmail.com", name: "Utkarsh", subject: "Review on Snippets", body: message})
20 |
21 | return { msg: "Review ent Successfully", status: true };
22 | } catch (error) {
23 | return { msg: "Internal Server error", status: false };
24 | }
25 | }
--------------------------------------------------------------------------------
/actions/SentMailForForgotPassword.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import Sendit from "@/helpers/SendIt";
3 | import prisma from "../prisma";
4 |
5 | interface VerifyuserProps {
6 | email: string,
7 | }
8 |
9 | export async function SentMailForForgotPassword(data: VerifyuserProps) {
10 | try {
11 | const { email } = data;
12 |
13 | if (!email) {
14 | return { msg: "Fields are empty", status: false };
15 | }
16 |
17 | const findUserEmail = await prisma.user.findFirst({
18 | where: {
19 | email: email
20 | }
21 | })
22 |
23 | if (!findUserEmail) {
24 | return { msg: "User not found", status: false };
25 |
26 | }
27 |
28 | const randomNumber = Math.floor(1000 + Math.random() * 9000).toString();
29 | await Sendit({ to: findUserEmail.email, name: findUserEmail.name, subject: "Email Verification", body: findUserEmail.verificationOtp })
30 |
31 |
32 | return { msg: "Email sent Successfully", status: true };
33 | } catch (error) {
34 | return { msg: "Internal Server Error", status: false };
35 | }
36 | }
--------------------------------------------------------------------------------
/actions/SetCoverImage.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { cookies } from "next/headers";
4 | import jwt, { JwtPayload } from "jsonwebtoken";
5 | import prisma from "../prisma";
6 |
7 |
8 | export async function SetCoverImage(imageUrl: string) {
9 | try {
10 | const cookieStore = cookies();
11 |
12 | const getCookie = cookieStore.get("snippets")?.value as string;
13 | const decodeCookieValue = jwt.verify(getCookie, process.env.JWT_SECRET!) as JwtPayload;
14 |
15 | const saveCoverImage = await prisma.user.update({
16 | where: {
17 | id: decodeCookieValue.id
18 | },
19 | data: {
20 | backgroundImage: imageUrl
21 | },
22 |
23 | select: {
24 | backgroundImage: true,
25 | },
26 | })
27 |
28 | let token = jwt.sign({
29 | id: decodeCookieValue.id, name: decodeCookieValue.name, email: decodeCookieValue.email, verified: decodeCookieValue.verified,
30 | }, process.env.JWT_SECRET!, { expiresIn: '10d' });
31 |
32 | const cookie = cookieStore.set('snippets', token, { httpOnly: true, sameSite: 'lax', expires: new Date(Date.now() + 10 * 24 * 60 * 60 * 1000) });
33 |
34 | return { msg: "Cover Image Saved Successfully", coverImage: saveCoverImage.backgroundImage, status: true };
35 | } catch (error) {
36 | return { msg: "Internal Server Error", status: false };
37 | }
38 | }
--------------------------------------------------------------------------------
/actions/SetProfileImage.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { cookies } from "next/headers";
4 | import jwt, { JwtPayload } from "jsonwebtoken";
5 | import prisma from "../prisma";
6 |
7 |
8 | export async function SetProfileImage(imageUrl: string) {
9 | try {
10 | const cookieStore = cookies();
11 |
12 | const getCookie = cookieStore.get("snippets")?.value as string;
13 | const decodeCookieValue = jwt.verify(getCookie, process.env.JWT_SECRET!) as JwtPayload;
14 |
15 | const saveProfileImage = await prisma.user.update({
16 | where: {
17 | id: decodeCookieValue.id
18 | },
19 | data: {
20 | profileImage: imageUrl
21 | },
22 |
23 | select: {
24 | profileImage: true,
25 | },
26 | })
27 |
28 | let token = jwt.sign({
29 | id: decodeCookieValue.id, name: decodeCookieValue.name, email: decodeCookieValue.email, verified: decodeCookieValue.verified,
30 | }, process.env.JWT_SECRET!, { expiresIn: '10d' });
31 |
32 | const cookie = cookieStore.set('snippets', token, { httpOnly: true, sameSite: 'lax', expires: new Date(Date.now() + 10 * 24 * 60 * 60 * 1000) });
33 |
34 | return { msg: "Cover Image Saved Successfully", saveProfileImage: saveProfileImage.profileImage, status: true };
35 | } catch (error) {
36 | return { msg: "Internal Server Error", status: false };
37 | }
38 | }
--------------------------------------------------------------------------------
/actions/UpdateBugStatus.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 |
6 | interface dataType {
7 | status: string,
8 | id: string
9 | }
10 |
11 | export async function UpdateBugStatus(data: dataType) {
12 | revalidatePath("/explore/bugtracker");
13 | try {
14 | const upDateStatus = await prisma.bugTracker.update({
15 | where: {
16 | id: data.id
17 | },
18 | data: {
19 | status: data.status
20 | }
21 | })
22 | return { msg: "Successfully updated status", status: true }
23 | } catch (error) {
24 | return { msg: "Internal Server error", status: false }
25 | }
26 | }
--------------------------------------------------------------------------------
/actions/VerifyEmailForForgotPassword.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import Sendit from "@/helpers/SendIt";
3 | import prisma from "../prisma";
4 |
5 | interface VerifyuserProps {
6 | email: string,
7 | otp: string
8 | }
9 |
10 | export async function VerifyEmailForForgotPassword(data: VerifyuserProps) {
11 | try {
12 | const { email, otp } = data;
13 | if (!email || !otp) {
14 | return { msg: "Fields are empty", status: false };
15 | }
16 |
17 | const findUserEmail = await prisma.user.findFirst({
18 | where: {
19 | email: email
20 | }
21 | })
22 | // console.log(findUserEmail)
23 |
24 | if (!findUserEmail) {
25 | return { msg: "User not found", status: false };
26 |
27 | }
28 |
29 | if (findUserEmail.verificationOtp != otp) {
30 | return { msg: "Wrong credentials", status: false };
31 |
32 | }
33 |
34 | const randomNumber = Math.floor(1000 + Math.random() * 9000).toString();
35 | await prisma.user.update({
36 | where: {
37 | id: findUserEmail.id
38 | },
39 | data: {
40 | verificationOtp: randomNumber,
41 | verified: true
42 | }
43 | })
44 |
45 | return { msg: "User verified Successfully", status: true };
46 | } catch (error) {
47 | return { msg: "Internal Server Error", status: false };
48 | }
49 | }
--------------------------------------------------------------------------------
/actions/VerifyUserAtSignup.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import prisma from "../prisma";
3 |
4 | interface VerifyuserProps {
5 | username: string,
6 | otp: string
7 | }
8 |
9 | export async function VerifyUserAtSignup(data: VerifyuserProps) {
10 | try {
11 | const { username, otp } = data;
12 |
13 | if (!username || !otp) {
14 | return { msg: "Fields are empty", status: false };
15 | }
16 |
17 | const findUserName = await prisma.user.findFirst({
18 | where: {
19 | username: username
20 | }
21 | })
22 |
23 | if (!findUserName) {
24 | return { msg: "User not found", status: false };
25 |
26 | }
27 |
28 | if (findUserName.verificationOtp != otp) {
29 | return { msg: "Internal Server Error", status: false };
30 | }
31 |
32 |
33 | const verifyUser = await prisma.user.update({
34 | where: {
35 | id: findUserName.id
36 | },
37 | data: {
38 | verified: true
39 | }
40 | })
41 |
42 | return {msg: "User is verified Successfully", status: true};
43 | } catch (error) {
44 | return { msg: "Internal Server Error", status: false };
45 | }
46 | }
--------------------------------------------------------------------------------
/actions/saveCommentsforFeed.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import prisma from "../prisma";
5 | import { GetUserDetails } from "./GetUserDetails";
6 |
7 | interface CommentData {
8 | text: string
9 | feedId: string;
10 | }
11 |
12 | export async function SaveCommentForFeed(data: CommentData) {
13 | revalidatePath("/feeds");
14 | try {
15 | const { feedId, text } = data;
16 | if (!feedId || !text) {
17 | return { msg: "Fields are empty", status: false }
18 | }
19 |
20 | const userDetails = await GetUserDetails();
21 |
22 | if (!userDetails) {
23 | return { msg: "Unauthorized access denied", status: false };
24 | }
25 |
26 | const saveComment = await prisma.feedsComment.create({
27 | data: {
28 | feedId: feedId,
29 | authorId: userDetails.decodeCookieValue?.id,
30 | content: text
31 | },
32 | include: {
33 | author: {
34 | select: {
35 | username: true,
36 | profileImage: true
37 | }
38 | }
39 | }
40 | })
41 |
42 |
43 | // console.log(saveComment)
44 | return { msg: "Comment sent successfully", commentData: saveComment, status: true };
45 | } catch (error) {
46 | return { msg: "Internal Server error", status: false }
47 | }
48 | }
--------------------------------------------------------------------------------
/actions/saveFeedPost.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { revalidatePath } from "next/cache";
4 | import { GetUserDetails } from "./GetUserDetails";
5 | import prisma from "../prisma";
6 | import { Redis } from "@upstash/redis";
7 |
8 | const redis = Redis.fromEnv();
9 |
10 | interface dataTypes {
11 | text: string,
12 | uploadedImageUrl: string
13 | }
14 |
15 | export async function SaveFeedPost(data: dataTypes) {
16 | revalidatePath("/feeds/uploadfeeds");
17 | try {
18 | const { text, uploadedImageUrl } = data;
19 | if (!text && !uploadedImageUrl) {
20 | return { msg: "Fields are empty", status: false };
21 | }
22 | const userDetails = await GetUserDetails();
23 | if (!userDetails) {
24 | return { msg: "User details not found", status: false };
25 | }
26 |
27 | const savePost = await prisma.feeds.create({
28 | data: {
29 | content: text,
30 | image: uploadedImageUrl,
31 | authorId: userDetails.decodeCookieValue?.id
32 | }
33 | })
34 | // console.log(savePost)
35 | await redis.del("latestfeed");
36 |
37 | return { msg: "Post Saved successfully!", status: true };
38 | } catch (error) {
39 | return { msg: "Internal Server Error", status: false };
40 | }
41 | }
--------------------------------------------------------------------------------
/actions/uploadSnippets.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import jwt, { JwtPayload } from "jsonwebtoken";
4 | import { cookies } from "next/headers";
5 | import prisma from "../prisma";
6 |
7 | interface SnippetsData {
8 | code: string,
9 | language: string,
10 | question: string
11 | }
12 |
13 | export async function UploadSnippets(data: SnippetsData) {
14 | revalidatePath("/uploadSnippets");
15 | try {
16 | const cookieStore = cookies();
17 | const getToken = cookieStore.get("snippets")?.value as string;
18 | const userDetails = jwt.verify(getToken, process.env.JWT_SECRET!) as JwtPayload;
19 |
20 | const findUser = await prisma.user.findFirst({
21 | where: {
22 | email: userDetails.email
23 | }
24 | })
25 |
26 | if (!findUser) {
27 | return { msg: "Unauthorized access", status: false };
28 | }
29 |
30 |
31 | await prisma.postSnippet.create({
32 | data: {
33 | question: data.question,
34 | code: data.code,
35 | programmingLanguage: data.language,
36 | author: {
37 | connect: { id: findUser.id },
38 | },
39 |
40 | }
41 | })
42 | return { msg: "Snippets saved successfully", status: true };
43 | } catch (error) {
44 | return { msg: "Internal Server error", status: false };
45 | }
46 | }
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "new-york",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "tailwind.config.ts",
8 | "css": "src/app/globals.css",
9 | "baseColor": "zinc",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils",
16 | "ui": "@/components/ui",
17 | "lib": "@/lib",
18 | "hooks": "@/hooks"
19 | }
20 | }
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | images: {
4 | domains: ["unsplash.com", "plus.unsplash.com", "t4.ftcdn.net", "res.cloudinary.com", "coolbackgrounds.io", "cdni.iconscout.com"],
5 | },
6 | };
7 |
8 | export default nextConfig;
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "snippet-nextjs",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "prisma generate && next build",
8 | "start": "next start",
9 | "lint": "next lint",
10 | "clean": "rm .next -r && next dev"
11 | },
12 | "dependencies": {
13 | "@dnd-kit/core": "^6.3.1",
14 | "@dnd-kit/sortable": "^10.0.0",
15 | "@dnd-kit/utilities": "^3.2.2",
16 | "@google/generative-ai": "^0.21.0",
17 | "@hookform/resolvers": "^3.9.0",
18 | "@monaco-editor/react": "^4.7.0",
19 | "@nextui-org/react": "^2.4.8",
20 | "@nextui-org/switch": "^2.0.34",
21 | "@prisma/client": "^5.20.0",
22 | "@radix-ui/react-avatar": "^1.1.2",
23 | "@radix-ui/react-checkbox": "^1.1.3",
24 | "@radix-ui/react-dialog": "^1.1.2",
25 | "@radix-ui/react-dropdown-menu": "^2.1.4",
26 | "@radix-ui/react-icons": "^1.3.0",
27 | "@radix-ui/react-label": "^2.1.1",
28 | "@radix-ui/react-popover": "^1.1.4",
29 | "@radix-ui/react-scroll-area": "^1.2.2",
30 | "@radix-ui/react-select": "^2.1.4",
31 | "@radix-ui/react-separator": "^1.1.0",
32 | "@radix-ui/react-slot": "^1.1.1",
33 | "@radix-ui/react-switch": "^1.1.2",
34 | "@radix-ui/react-toast": "^1.2.2",
35 | "@react-email/components": "^0.0.25",
36 | "@react-email/render": "^1.0.1",
37 | "@tabler/icons-react": "^3.21.0",
38 | "@types/bcryptjs": "^2.4.6",
39 | "@types/jsonwebtoken": "^9.0.7",
40 | "@types/nodemailer": "^6.4.16",
41 | "@types/pusher-js": "^4.2.2",
42 | "@types/react-syntax-highlighter": "^15.5.13",
43 | "@upstash/redis": "^1.34.3",
44 | "axios": "^1.7.7",
45 | "bcryptjs": "^2.4.3",
46 | "class-variance-authority": "^0.7.1",
47 | "cloudinary": "^2.5.1",
48 | "clsx": "^2.1.1",
49 | "date-fns": "^4.1.0",
50 | "framer-motion": "^11.11.11",
51 | "jsonwebtoken": "^9.0.2",
52 | "lucide-react": "^0.453.0",
53 | "monaco-editor": "^0.52.2",
54 | "next": "14.2.15",
55 | "next-themes": "^0.3.0",
56 | "nodemailer": "^6.9.15",
57 | "openai": "^4.89.0",
58 | "pusher": "^5.2.0",
59 | "pusher-js": "^8.4.0-rc2",
60 | "react": "^18",
61 | "react-dom": "^18",
62 | "react-dropzone": "^14.3.5",
63 | "react-hook-form": "^7.53.0",
64 | "react-icons": "^5.3.0",
65 | "react-syntax-highlighter": "^15.6.1",
66 | "react-toastify": "^10.0.6",
67 | "tailwind-merge": "^2.5.4",
68 | "tailwindcss-animate": "^1.0.7",
69 | "usehooks-ts": "^3.1.0",
70 | "zod": "^3.23.8"
71 | },
72 | "devDependencies": {
73 | "@types/node": "^20",
74 | "@types/react": "^18",
75 | "@types/react-dom": "^18",
76 | "eslint": "^8",
77 | "eslint-config-next": "14.2.15",
78 | "postcss": "^8",
79 | "prisma": "^5.20.0",
80 | "tailwindcss": "^3.4.1",
81 | "typescript": "^5"
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('postcss-load-config').Config} */
2 | const config = {
3 | plugins: {
4 | tailwindcss: {},
5 | },
6 | };
7 |
8 | export default config;
9 |
--------------------------------------------------------------------------------
/prisma/index.ts:
--------------------------------------------------------------------------------
1 | //@ts-nocheck
2 | import { PrismaClient } from "@prisma/client";
3 |
4 | let prisma: PrismaClient;
5 | declare global {
6 | namespace NodeJS {
7 | interface Global {
8 | prisma: PrismaClient;
9 | }
10 | }
11 | }
12 |
13 | if (process.env.NODE_ENV === "production") {
14 | prisma = new PrismaClient();
15 | } else {
16 | if (!global.prisma) {
17 | global.prisma = new PrismaClient();
18 | }
19 | prisma = global.prisma;
20 | }
21 |
22 | export default prisma;
--------------------------------------------------------------------------------
/prisma/schema.prisma:
--------------------------------------------------------------------------------
1 | // This is your Prisma schema file,
2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema
3 |
4 | // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
5 | // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
6 |
7 | generator client {
8 | provider = "prisma-client-js"
9 | }
10 |
11 | datasource db {
12 | provider = "mongodb"
13 | url = env("DATABASE_URL")
14 | }
15 |
16 | model User {
17 | id String @id @default(auto()) @map("_id") @db.ObjectId
18 | name String
19 | username String
20 | email String
21 | password String
22 | backgroundImage String @default("")
23 | profileImage String @default("")
24 | about String @default("")
25 | workplace String @default("")
26 | location String @default("")
27 | badges String[]
28 | snippetPosts PostSnippet[]
29 | comments Comment[]
30 | chats Chat[]
31 | friendOf Friends[]
32 | Feed Feeds[]
33 | verificationOtp String
34 | verified Boolean @default(false)
35 | createdAt DateTime @default(now())
36 | updatedAt DateTime @updatedAt
37 | FeedsComment FeedsComment[]
38 | FeedsLikes FeedsLikes[]
39 | BugTracker bugTracker[]
40 | }
41 |
42 | model PostSnippet {
43 | id String @id @default(auto()) @map("_id") @db.ObjectId
44 | programmingLanguage String
45 | code String
46 | question String?
47 | author User @relation(fields: [authorId], references: [id])
48 | authorId String @db.ObjectId
49 | comments Comment[] @relation("SnippetComments")
50 | createdAt DateTime @default(now())
51 | updatedAt DateTime @updatedAt
52 | }
53 |
54 | model Comment {
55 | id String @id @default(auto()) @map("_id") @db.ObjectId
56 | content String
57 | post PostSnippet @relation(fields: [postId], references: [id], name: "SnippetComments")
58 | postId String @db.ObjectId
59 | author User @relation(fields: [authorId], references: [id])
60 | authorId String @db.ObjectId
61 | createdAt DateTime @default(now())
62 | updatedAt DateTime @updatedAt
63 | }
64 |
65 | model Chat {
66 | id String @id @default(auto()) @map("_id") @db.ObjectId
67 | text String
68 | sender User @relation(fields: [senderId], references: [id])
69 | senderId String @db.ObjectId
70 | receiverId String @db.ObjectId
71 | createdAt DateTime @default(now())
72 | updatedAt DateTime @updatedAt
73 | }
74 |
75 | model Friends {
76 | id String @id @default(auto()) @map("_id") @db.ObjectId
77 | userId String
78 | friend User @relation(fields: [friendId], references: [id])
79 | friendId String @db.ObjectId
80 | }
81 |
82 | model Feeds {
83 | id String @id @default(auto()) @map("_id") @db.ObjectId
84 | author User @relation(fields: [authorId], references: [id])
85 | authorId String @db.ObjectId
86 | content String?
87 | image String?
88 | createdAt DateTime @default(now())
89 | updatedAt DateTime @updatedAt
90 | comments FeedsComment[]
91 | feedLikes FeedsLikes[]
92 | }
93 |
94 | model FeedsComment {
95 | id String @id @default(auto()) @map("_id") @db.ObjectId
96 | content String
97 | feed Feeds @relation(fields: [feedId], references: [id], onDelete: Cascade)
98 | feedId String @db.ObjectId
99 | author User @relation(fields: [authorId], references: [id])
100 | authorId String @db.ObjectId
101 | createdAt DateTime @default(now())
102 | updatedAt DateTime @updatedAt
103 | }
104 |
105 | model FeedsLikes {
106 | id String @id @default(auto()) @map("_id") @db.ObjectId
107 | feedId String @db.ObjectId
108 | feed Feeds @relation(fields: [feedId], references: [id], onDelete: Cascade)
109 | authorId String @db.ObjectId
110 | author User @relation(fields: [authorId], references: [id])
111 | createdAt DateTime @default(now())
112 | updatedAt DateTime @updatedAt
113 | }
114 |
115 |
116 | model bugTracker{
117 | id String @id @default(auto()) @map("_id") @db.ObjectId
118 | status String
119 | bugText String
120 | startDate DateTime
121 | endDate DateTime
122 | userId String @db.ObjectId
123 | user User @relation(fields: [userId], references: [id])
124 | createdAt DateTime @default(now())
125 | updatedAt DateTime @updatedAt
126 | }
--------------------------------------------------------------------------------
/public/linear.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iutkarsh077/Snippets-SAAS-Production/fcc957b6898a12e52f68c9de38d83f72b4a49944/public/linear.webp
--------------------------------------------------------------------------------
/src/app/(auth)/_components/ChangePassword.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { motion } from "framer-motion";
3 | import Link from "next/link";
4 | import LeftSideSnippet from "../_components/LeftSideSnippet";
5 | import { useForm } from "react-hook-form";
6 | import {
7 | changePasswordTypes,
8 | changePasswordResolver,
9 | } from "@/types/ChangePasswordTypes";
10 | import { ChangePasswordActions } from "../../../../actions/ChangePassword";
11 | import { useState } from "react";
12 | import { Loader2 } from "lucide-react";
13 | import { useRouter } from "next/navigation";
14 | const ChangePassword = ({userEmail}:{userEmail: string}) => {
15 | const [loading, setLoading] = useState(false);
16 | const router = useRouter();
17 | const {
18 | register,
19 | handleSubmit,
20 | formState: { errors },
21 | } = useForm({
22 | resolver: changePasswordResolver,
23 | defaultValues: {
24 | password: "",
25 | confirmPassword: "",
26 | },
27 | });
28 |
29 | const VerifyEmailForgotPassword = async (data: changePasswordTypes) => {
30 | if (data.password !== data.confirmPassword || !userEmail) {
31 | return;
32 | }
33 | setLoading(true)
34 | try {
35 | const userData = {
36 | confirmPassword: data.confirmPassword,
37 | password: data.password,
38 | email: userEmail
39 | }
40 | const res = await ChangePasswordActions(userData);
41 | if (res.status === false) {
42 | throw new Error(res.msg);
43 | }
44 | router.push("/sign-up");
45 | } catch (error) {
46 | // console.log(error);
47 | }
48 | finally{
49 | setLoading(false);
50 | }
51 | };
52 | return (
53 |
54 |
55 |
56 |
62 |
63 | Reset Password
64 |
65 |
66 | Change your Password here
67 |
68 |
69 | {/* Form */}
70 |
128 |
129 |
130 | Dont have an account?{" "}
131 |
135 | Sign up
136 |
137 |
138 |
139 |
140 | );
141 | };
142 |
143 | export default ChangePassword;
144 |
--------------------------------------------------------------------------------
/src/app/(auth)/_components/LeftSideSnippet.tsx:
--------------------------------------------------------------------------------
1 | import { motion } from "framer-motion";
2 | const LeftSideSnippet = () => {
3 | return (
4 |
10 |
11 | SNIPPETS
12 |
13 |
14 | );
15 | };
16 |
17 | export default LeftSideSnippet;
18 |
--------------------------------------------------------------------------------
/src/app/(auth)/_components/OtpForSignup.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useState } from "react";
3 | import { motion } from "framer-motion";
4 | import { useForm } from "react-hook-form";
5 | import { z } from "zod";
6 | import { zodResolver } from "@hookform/resolvers/zod";
7 | import LeftSideSnippet from "./LeftSideSnippet";
8 | import { VerifyUserAtSignup } from "../../../../actions/VerifyUserAtSignup";
9 | import { useRouter } from "next/navigation";
10 |
11 | const otpSchema = z.object({
12 | otp: z
13 | .string()
14 | .min(4, {
15 | message: "Otp must be at least 4 characters",
16 | })
17 | .max(20, {
18 | message: "Otp cannot exceed 20 characters",
19 | }),
20 | });
21 |
22 | type OtpType = z.infer;
23 |
24 | const OtpForSignup = ({ username }: { username: string }) => {
25 | const [otp, setOtp] = useState("");
26 | const router = useRouter();
27 | const {
28 | register,
29 | handleSubmit,
30 | formState: { errors },
31 | } = useForm({
32 | resolver: zodResolver(otpSchema),
33 | defaultValues: {
34 | otp: "",
35 | },
36 | });
37 |
38 | const OtpSubmit = async (data: OtpType) => {
39 | try {
40 | const mydata = {
41 | otp: data.otp,
42 | username: username,
43 | };
44 | const res = await VerifyUserAtSignup(mydata);
45 |
46 | if (res.status === false) {
47 | throw new Error(res.msg);
48 | }
49 |
50 | // console.log(res);
51 | router.push("/login");
52 | } catch (error) {
53 | // console.log(error);
54 | }
55 | };
56 |
57 | return (
58 |
59 |
60 |
66 |
67 | Sign up
68 |
69 |
70 | Create a new account
71 |
72 |
73 | {/* Form */}
74 |
109 |
110 |
111 | );
112 | };
113 |
114 | export default OtpForSignup;
115 |
--------------------------------------------------------------------------------
/src/app/(home)/_components/Card.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { motion } from "framer-motion";
3 | import { Clipboard, Check } from "lucide-react";
4 | import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
5 | import { atomDark } from "react-syntax-highlighter/dist/esm/styles/prism";
6 | import Link from "next/link";
7 |
8 | export default function CodeCard({ snippet }: any) {
9 | const [copied, setCopied] = useState(false);
10 |
11 | const copyToClipboard = () => {
12 | navigator.clipboard.writeText(snippet.code);
13 | setCopied(true);
14 | setTimeout(() => setCopied(false), 2000);
15 | };
16 |
17 | const truncateWord = (code: string, length :number) =>{
18 | if(code.length <= 300) return code;
19 |
20 | return code.slice(0, 300);
21 | }
22 |
23 | const trimSentence = truncateWord(snippet.code, 200);
24 |
25 | return (
26 | <>
27 |
34 |
35 |
36 |
41 |
47 | {copied ? : }
48 |
49 |
50 |
51 |
64 | {trimSentence}
65 |
66 |
67 |
68 |
74 |
75 | {snippet.programmingLanguage}
76 |
77 |
78 | {snippet.code.split("\n").length}
79 |
80 |
81 |
82 | >
83 | );
84 | }
85 |
--------------------------------------------------------------------------------
/src/app/(home)/_components/Footer.tsx:
--------------------------------------------------------------------------------
1 | import { motion } from "framer-motion";
2 | import { FaTwitter, FaGithub, FaLinkedin } from "react-icons/fa";
3 | import Link from "next/link";
4 | export default function Footer() {
5 | return (
6 |
12 |
13 |
14 |
15 |
21 | Snippets
22 |
23 |
24 |
25 |
31 |
32 | Dashboard
33 |
34 |
35 | Snippets
36 |
37 |
38 | DevChat
39 |
40 |
41 | Artify
42 |
43 |
44 |
45 | Review Us
46 |
47 |
48 |
49 | {/* Social Media Icons */}
50 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | {/* Copyright Text */}
69 |
75 | © {new Date().getFullYear()} SnippetApp. All rights reserved.
76 |
77 |
78 |
79 | );
80 | }
81 |
--------------------------------------------------------------------------------
/src/app/(home)/_components/Header.tsx:
--------------------------------------------------------------------------------
1 | import { BackgroundBeamsWithCollision } from "@/components/BackgroundBeamsWithCollision";
2 |
3 | const Header = () => {
4 | return (
5 |
6 |
7 |
8 | What's cooler than SNIPPETS?{" "}
9 |
10 | Exploding snippets.
11 |
12 |
13 |
14 |
15 | )
16 | }
17 |
18 | export default Header
19 |
--------------------------------------------------------------------------------
/src/app/(home)/_components/HeroScrollDemo.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { ContainerScroll } from "@/components/container-scroll-animation";
3 |
4 | export function HeroScrollDemo() {
5 | return (
6 |
7 |
10 |
11 | Unleash the power of
12 |
13 | Code Snippets
14 |
15 |
16 | >
17 | }
18 | >
19 |
27 |
28 |
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/src/app/(home)/_components/Home.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useCallback, useEffect, useState } from "react";
3 | import Header from "../_components/Header";
4 | import CodeCard from "../_components/Card";
5 | import { HeroScrollDemo } from "../_components/HeroScrollDemo";
6 | import { CardHoverEffectDemo } from "../_components/HoverEffect";
7 | import Footer from "../_components/Footer";
8 | import { GetAllSnippets } from "../../../../actions/GetAllSnippets";
9 | import { SnippetType } from "@/app/snippets/page";
10 | import { motion } from "framer-motion";
11 | import ImageCard, {
12 | ImageCardProps,
13 | } from "@/app/feeds/_components/HeaderImageCard";
14 | import { DeleteFeed } from "../../../../actions/DeleteFeed";
15 | import { GetFeedByProfile } from "../../../../actions/GetfeedByProfile";
16 | import { GetLatestFeed } from "../../../../actions/GetLatestFeed";
17 |
18 | const HomeSection = () => {
19 | const [cardData, setCardData] = useState(null);
20 | const [loading, setLoading] = useState(false);
21 | const [snippets, setSnippets] = useState(null);
22 |
23 | const fetchFeedData = useCallback(async () => {
24 | try {
25 | const res = await GetLatestFeed();
26 | if (res.status === false) {
27 | throw new Error(res.msg);
28 | }
29 | // console.log(res);
30 | setCardData(res?.feedsData);
31 | } catch (error) {
32 | // console.log(error);
33 | } finally {
34 | setLoading(false);
35 | }
36 | }, []);
37 |
38 | useEffect(() => {
39 | fetchFeedData();
40 | }, []);
41 |
42 | useEffect(() => {
43 | const getAllSnippets = async () => {
44 | setLoading(true);
45 | const res = await GetAllSnippets();
46 | if (res && res.data) {
47 | setSnippets(res.data as any);
48 | // console.log(res);
49 | }
50 | setLoading(false);
51 | };
52 | getAllSnippets();
53 | }, []);
54 |
55 | const handleDeleteFeed = async (feedId: string) => {
56 | try {
57 | setCardData((prevData: any) =>
58 | prevData ? prevData.filter((feed: any) => feed.id !== feedId) : prevData
59 | );
60 | const res = await DeleteFeed(feedId);
61 | if (res.status === false) {
62 | throw new Error(res.msg);
63 | }
64 | } catch (error) {
65 | // console.log(error);
66 | }
67 | };
68 |
69 | return (
70 | <>
71 |
72 |
73 | {cardData
74 | ?.slice(2, 5)
75 | .map((cardDataItems: ImageCardProps, index: number) => (
76 |
83 |
88 |
89 | ))}
90 |
91 |
92 |
93 | {snippets
94 | ?.sort(
95 | (a: any, b: any) =>
96 | new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
97 | )
98 | .slice(0, 6)
99 | .map((snippet, index) => (
100 |
101 |
102 |
103 | ))}
104 |
105 |
106 |
107 | >
108 | );
109 | };
110 |
111 | export default HomeSection;
112 |
--------------------------------------------------------------------------------
/src/app/(home)/_components/HoverEffect.tsx:
--------------------------------------------------------------------------------
1 | import { HoverEffect } from "@/components/card-hover-effect";
2 |
3 | export function CardHoverEffectDemo() {
4 | return (
5 |
6 |
7 |
8 | );
9 | }
10 | export const projects = [
11 | {
12 | title: "JavaScript Snippet",
13 | description:
14 | "A collection of useful JavaScript code snippets that help with common tasks, such as array manipulation, DOM interaction, and async handling.",
15 | link: "https://yoursnippetsapp.com/javascript",
16 | },
17 | {
18 | title: "Python Snippet",
19 | description:
20 | "Explore Python code snippets covering a range of topics, including data structures, algorithms, and web scraping for your next project.",
21 | link: "https://yoursnippetsapp.com/python",
22 | },
23 | {
24 | title: "React Snippet",
25 | description:
26 | "Find reusable React components and hooks for common functionality, including form handling, routing, and API requests.",
27 | link: "https://yoursnippetsapp.com/react",
28 | },
29 | {
30 | title: "CSS Snippet",
31 | description:
32 | "A variety of CSS snippets for layouts, animations, and responsive design to enhance the visual appeal of your web projects.",
33 | link: "https://yoursnippetsapp.com/css",
34 | },
35 | {
36 | title: "Node.js Snippet",
37 | description:
38 | "Backend-focused Node.js snippets to handle everything from server setup to working with APIs, databases, and real-time applications.",
39 | link: "https://yoursnippetsapp.com/nodejs",
40 | },
41 | {
42 | title: "SQL Snippet",
43 | description:
44 | "Efficient SQL queries and database manipulation snippets that simplify tasks like data retrieval, filtering, and updates.",
45 | link: "https://yoursnippetsapp.com/sql",
46 | },
47 | ];
48 |
--------------------------------------------------------------------------------
/src/app/api/ImageUpload/route.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { CloudinaryUploadResult, uploadImageCloudinary } from "@/lib/cloudinaryImageUploader";
4 | import { revalidatePath } from "next/cache";
5 | import { cookies } from "next/headers";
6 | import { NextResponse } from "next/server";
7 |
8 | export async function POST(req: Request){
9 | const formData = await req.formData();
10 | const image = formData.get("file") as File;
11 | revalidatePath("/profile");
12 | try {
13 |
14 | const cookieStore = cookies();
15 | const userCookie1 = cookieStore.get("snippets")?.value;
16 |
17 | if(!userCookie1){
18 | return NextResponse.json({message: "Upload Failed", status: false}, {status: 401});
19 | }
20 |
21 | const CloudinaryImageLink = await uploadImageCloudinary(image, "posts") as CloudinaryUploadResult;
22 |
23 | const imageUrl = CloudinaryImageLink.url;
24 | return NextResponse.json({message: "Successfully Image uploaded", status: true, imageUrl}, {status: 201});
25 | } catch (error) {
26 | return NextResponse.json({message: "Upload Failed", status: false}, {status: 401});
27 | }
28 | }
--------------------------------------------------------------------------------
/src/app/api/ImageUploadForLink/route.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { CloudinaryUploadResult, uploadImageCloudinary } from "@/lib/cloudinaryImageUploader";
4 | import { revalidatePath } from "next/cache";
5 | import { NextResponse } from "next/server";
6 |
7 | export async function POST(req: Request){
8 | const formData = await req.formData();
9 | const image = formData.get("file") as File;
10 | revalidatePath("/explore");
11 | try {
12 | const CloudinaryImageLink = await uploadImageCloudinary(image, "posts") as CloudinaryUploadResult;
13 |
14 | const imageUrl = CloudinaryImageLink.url;
15 | return NextResponse.json({message: "Successfully Image uploaded", status: true, imageUrl}, {status: 201});
16 | } catch (error) {
17 | return NextResponse.json({message: "Upload Failed", status: false}, {status: 401});
18 | }
19 | }
--------------------------------------------------------------------------------
/src/app/api/SaveBug/route.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { NextResponse } from "next/server";
4 | import { GetUserDetails } from "../../../../actions/GetUserDetails";
5 | import prisma from "../../../../prisma";
6 |
7 | export async function POST(req: Request) {
8 | try {
9 | const { text, startDate, endDate, status } = await req.json();
10 |
11 | if (!text || !startDate || !endDate || !status) {
12 | return NextResponse.json(
13 | { msg: "Missing required fields", status: false },
14 | { status: 400 }
15 | );
16 | }
17 |
18 | const parsedStartDate = new Date(startDate);
19 | const parsedEndDate = new Date(endDate);
20 |
21 |
22 |
23 | const getUser = await GetUserDetails();
24 | if (!getUser?.decodeCookieValue?.id) {
25 | return NextResponse.json(
26 | { msg: "Unauthorized access", status: false },
27 | { status: 401 }
28 | );
29 | }
30 |
31 | const data = await prisma.bugTracker.create({
32 | data: {
33 | status,
34 | bugText: text,
35 | startDate: parsedStartDate,
36 | endDate: parsedEndDate,
37 | userId: getUser.decodeCookieValue.id,
38 | },
39 | });
40 |
41 |
42 | return NextResponse.json({ msg: "All Set", status: true }, { status: 201 });
43 | } catch (error) {
44 | console.error("Error in POST /bugTracker:", error);
45 | return NextResponse.json(
46 | { msg: "Internal Server Error", status: false },
47 | { status: 500 }
48 | );
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/api/generate/route.ts:
--------------------------------------------------------------------------------
1 | import { OpenAI } from 'openai';
2 | import { NextResponse } from 'next/server';
3 | export const dynamic = "force-dynamic";
4 |
5 | const client = new OpenAI({
6 | baseURL: 'https://api.studio.nebius.com/v1/',
7 | apiKey: process.env.NEBIUS_API_KEY,
8 | });
9 |
10 | export async function POST(req: Request) {
11 | try {
12 | const { prompt } = await req.json();
13 |
14 | if (!prompt) {
15 | return NextResponse.json(
16 | { error: 'Prompt is required' },
17 | { status: 400 }
18 | );
19 | }
20 |
21 | const response = await client.images.generate({
22 | "model": "black-forest-labs/flux-dev",
23 | "response_format": "url",
24 | "extra_body": {
25 | "response_extension": "webp",
26 | "width": 1024,
27 | "height": 1024,
28 | "num_inference_steps": 28,
29 | "negative_prompt": "",
30 | "seed": -1
31 | },
32 | "prompt": prompt
33 | } as any)
34 |
35 | // console.log("Response of generated image", response);
36 |
37 | return NextResponse.json({ imageUrl: response.data[0].url });
38 | } catch (error: any) {
39 | console.error('Error generating image:', error);
40 | return NextResponse.json(
41 | { error: error.message || 'Failed to generate image' },
42 | { status: 500 }
43 | );
44 | }
45 | }
--------------------------------------------------------------------------------
/src/app/api/pusher/auth/route.ts:
--------------------------------------------------------------------------------
1 |
2 | import { getPusherInstance } from "@/lib/pusher/server/index";
3 |
4 | const pusherServer = getPusherInstance();
5 |
6 | export async function POST(req: Request) {
7 | console.log("authenticating pusher perms...")
8 | const data = await req.text();
9 | const [socketId, channelName] = data
10 | .split("&")
11 | .map((str) => str.split("=")[1]);
12 |
13 | // logic to check user permissions
14 |
15 | const authResponse = pusherServer.authorizeChannel(socketId, channelName);
16 |
17 | return new Response(JSON.stringify(authResponse));
18 | }
--------------------------------------------------------------------------------
/src/app/api/test/route.ts:
--------------------------------------------------------------------------------
1 | import { NextResponse } from 'next/server'
2 | import { getPusherInstance } from '@/lib/pusher/server/index';
3 | import prisma from '../../../../prisma';
4 | import { GetUserDetails } from '../../../../actions/GetUserDetails';
5 | const pusherServer = getPusherInstance();
6 |
7 | export async function POST(req: Request, res: Response) {
8 | const { message, roomId, receiver, senderId } = await req.json();
9 | console.log(message, roomId)
10 | try {
11 |
12 | await pusherServer.trigger(
13 | roomId,
14 | "chat",
15 | {
16 | senderId,
17 | text: message,
18 | user: "ree",
19 | createdAt: new Date(),
20 | }
21 | )
22 |
23 | const getSenderDetails = await GetUserDetails();
24 | await prisma.chat.create({
25 | data: {
26 | text: message,
27 | senderId: getSenderDetails?.decodeCookieValue?.id,
28 | receiverId: receiver
29 | }
30 | })
31 |
32 | return NextResponse.json({ message: "Sockets tested" }, { status: 200 })
33 | } catch (error) {
34 | console.error(error)
35 | return NextResponse.json({ message: "Failed to test sockets", error: error }, { status: 500 })
36 | }
37 | }
--------------------------------------------------------------------------------
/src/app/askAi/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useState, useEffect, useRef } from "react";
3 | import { motion, AnimatePresence } from "framer-motion";
4 | import { toast } from "react-toastify";
5 | import { Loader2 } from "lucide-react";
6 | import { TextGenerateEffect } from "@/components/text-generate-effect";
7 | import { askAI } from "../../../actions/GeminiResponse";
8 |
9 | const Artify = () => {
10 | const [input, setInput] = useState("");
11 | const [responseFromGemini, setResponseFromGemini] = useState<
12 | { question: string; answer: string }[]
13 | >([]);
14 |
15 | const [isLoading, setIsLoading] = useState(false);
16 | const inputRef = useRef(null);
17 |
18 | const handleAiResponse = async () => {
19 | if (!input.trim()) {
20 | toast.error("Please enter a question");
21 | return;
22 | }
23 |
24 | setIsLoading(true);
25 | try {
26 | const res = await askAI({ question: input });
27 | if (res.status === false) {
28 | throw new Error("Something went wrong");
29 | }
30 | if (res.data) {
31 | const cleanedText = res.data.replace(/(\*\*|\*|```|`|``)/g, "");
32 | setResponseFromGemini((prev) => [
33 | ...prev,
34 | { question: input, answer: cleanedText },
35 | ]);
36 | }
37 | setInput("");
38 | inputRef.current?.focus();
39 | } catch (error: any) {
40 | const errorMessage = error ?? "An unknown error occurred";
41 | toast.error(errorMessage);
42 | } finally {
43 | setIsLoading(false);
44 | }
45 | };
46 |
47 | useEffect(() => {
48 | // Scroll to bottom when new response is added
49 | window.scrollTo(0, document.body.scrollHeight);
50 | }, [responseFromGemini]);
51 |
52 | const handleKeyPress = (event: React.KeyboardEvent) => {
53 | if (event.key === "Enter") {
54 | handleAiResponse();
55 | }
56 | };
57 | return (
58 |
59 |
60 | {responseFromGemini.length > 0 && (
61 |
67 |
68 | Artify Response:
69 |
70 |
71 | {responseFromGemini.map((res: any, index: number) => (
72 |
73 |
74 | {res.question
75 | .split(" ")
76 | .map((words: any, index: number) => (
77 |
{words}
78 | ))}
79 |
80 |
81 | {}
82 |
83 |
84 |
85 |
86 | ))}
87 |
88 |
89 | )}
90 |
91 |
92 |
98 |
99 | setInput(e.target.value)}
106 | className="flex-grow rounded-md border border-gray-300 p-2 focus:outline-none focus:ring-2 focus:ring-purple-500"
107 | />
108 |
115 | {isLoading ? (
116 |
117 | ) : (
118 | "Artify"
119 | )}
120 |
121 |
122 |
123 |
124 | );
125 | };
126 |
127 | export default Artify;
128 |
--------------------------------------------------------------------------------
/src/app/explore/_components/ExploreCards.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import Image from "next/image";
3 | import React from "react";
4 | import { CardBody, CardContainer, CardItem } from "@/components/ui/3d-card";
5 | import Link from "next/link";
6 |
7 | export interface propTypes {
8 | title: string;
9 | description: string;
10 | path: string;
11 | mainImage: string;
12 | }
13 |
14 | export function ExploreCard({
15 | title,
16 | description,
17 | path,
18 | mainImage,
19 | }: propTypes) {
20 | return (
21 |
22 |
23 |
24 |
28 | {title}
29 |
30 |
35 | {description}
36 |
37 |
38 |
45 |
46 |
47 |
48 |
55 | Try now →
56 |
57 |
58 |
59 |
64 | Get In
65 |
66 |
67 |
68 |
69 |
70 |
71 | );
72 | }
73 |
--------------------------------------------------------------------------------
/src/app/explore/bugtracker/_components/Kanban.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { Card } from '@/components/ui/card';
4 | import { cn } from '@/lib/utils';
5 | import {
6 | DndContext,
7 | rectIntersection,
8 | useDraggable,
9 | useDroppable,
10 | } from '@dnd-kit/core';
11 | import type { DragEndEvent } from '@dnd-kit/core';
12 | import type { ReactNode } from 'react';
13 |
14 | export type Status = {
15 | id: string;
16 | name: string;
17 | color: string;
18 | };
19 |
20 | export type Feature = {
21 | id: string;
22 | name: string;
23 | startAt: Date;
24 | endAt: Date;
25 | status: Status;
26 | };
27 |
28 | export type KanbanBoardProps = {
29 | id: Status['id'];
30 | children: ReactNode;
31 | className?: string;
32 | };
33 |
34 | export const KanbanBoard = ({ id, children, className }: KanbanBoardProps) => {
35 | const { isOver, setNodeRef } = useDroppable({ id });
36 |
37 | return (
38 |
46 | {children}
47 |
48 | );
49 | };
50 |
51 | export type KanbanCardProps = Pick & {
52 | index: number;
53 | parent: string;
54 | children?: ReactNode;
55 | className?: string;
56 | };
57 |
58 | export const KanbanCard = ({
59 | id,
60 | name,
61 | index,
62 | parent,
63 | children,
64 | className,
65 | }: KanbanCardProps) => {
66 | const { attributes, listeners, setNodeRef, transform, isDragging } =
67 | useDraggable({
68 | id,
69 | data: { index, parent },
70 | });
71 |
72 | return (
73 |
88 | {children ?? {name}
}
89 |
90 | );
91 | };
92 |
93 | export type KanbanCardsProps = {
94 | children: ReactNode;
95 | className?: string;
96 | };
97 |
98 | export const KanbanCards = ({ children, className }: KanbanCardsProps) => (
99 | {children}
100 | );
101 |
102 | export type KanbanHeaderProps =
103 | | {
104 | children: ReactNode;
105 | }
106 | | {
107 | name: Status['name'];
108 | color: Status['color'];
109 | className?: string;
110 | };
111 |
112 | export const KanbanHeader = (props: KanbanHeaderProps) =>
113 | 'children' in props ? (
114 | props.children
115 | ) : (
116 |
117 |
121 |
{props.name}
122 |
123 | );
124 |
125 | export type KanbanProviderProps = {
126 | children: ReactNode;
127 | onDragEnd: (event: DragEndEvent) => void;
128 | className?: string;
129 | };
130 |
131 | export const KanbanProvider = ({
132 | children,
133 | onDragEnd,
134 | className,
135 | }: KanbanProviderProps) => (
136 |
137 |
140 | {children}
141 |
142 |
143 | );
144 |
--------------------------------------------------------------------------------
/src/app/explore/bugtracker/page.tsx:
--------------------------------------------------------------------------------
1 |
2 | import React from "react";
3 | import { KanbanExample } from "./_components/Demo";
4 |
5 | const BugTracker = () => {
6 | return (
7 |
14 | );
15 | };
16 |
17 | export default BugTracker;
18 |
--------------------------------------------------------------------------------
/src/app/explore/code-editor/page.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import MyEditor from './_components/CustomEditor'
3 |
4 | const CodeEditor = () => {
5 | return (
6 |
7 |
8 |
9 | )
10 | }
11 |
12 | export default CodeEditor
13 |
--------------------------------------------------------------------------------
/src/app/explore/image-generator/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useState } from "react";
4 | import { Download, Wand2 } from "lucide-react";
5 | import { Button } from "@/components/ui/button";
6 | import { Textarea } from "@/components/ui/textarea";
7 | import { Card } from "@/components/ui/card";
8 | import { useToast } from "@/hooks/use-toast";
9 |
10 | export default function Home() {
11 | const [prompt, setPrompt] = useState("");
12 | const [image, setImage] = useState(null);
13 | const [loading, setLoading] = useState(false);
14 | const { toast } = useToast();
15 |
16 | const generateImage = async () => {
17 | if (!prompt.trim()) {
18 | toast({
19 | title: "Error",
20 | description: "Please enter a prompt",
21 | variant: "destructive",
22 | });
23 | return;
24 | }
25 |
26 | try {
27 | setLoading(true);
28 | const response = await fetch("/api/generate", {
29 | method: "POST",
30 | headers: {
31 | "Content-Type": "application/json",
32 | },
33 | body: JSON.stringify({ prompt }),
34 | });
35 |
36 | const data = await response.json();
37 |
38 | if (!response.ok) {
39 | throw new Error(data.error || "Failed to generate image");
40 | }
41 | // console.log(data)
42 | setImage(data.imageUrl);
43 | } catch (error: any) {
44 | toast({
45 | title: "Error",
46 | description: error.message || "Failed to generate image",
47 | variant: "destructive",
48 | });
49 | } finally {
50 | setLoading(false);
51 | }
52 | };
53 |
54 | const downloadImage = async () =>{
55 | try {
56 | const response = await fetch(image as string);
57 | const blob = await response.blob();
58 | const url = URL.createObjectURL(blob);
59 | const a = document.createElement("a");
60 | a.href = url;
61 | a.download = `image/${Math.floor(Math.random() * 10000)}.png`;
62 | document.body.appendChild(a);
63 | a.click();
64 | document.body.removeChild(a);
65 | URL.revokeObjectURL(url);
66 | } catch (error) {
67 | console.error("Error downloading the image:", error);
68 | toast({
69 | title: "Something went wrong",
70 | description: "Failed to download image, Please again after sometime."
71 | })
72 | }
73 | }
74 |
75 | return (
76 |
77 |
78 |
79 |
80 | Unleash Your Imagination with AI!
81 |
82 |
83 | Turn your ideas into breathtaking visuals in seconds.
84 |
85 |
86 |
87 |
88 |
89 |
110 |
111 | {image && (
112 |
113 |
114 |

119 |
120 |
121 |
122 | {prompt}
123 |
124 |
125 |
126 |
127 | )}
128 |
129 |
130 |
131 | );
132 | }
--------------------------------------------------------------------------------
/src/app/explore/imageUpload/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { FileUpload } from "@/components/ui/file-upload";
3 | import React, { useState } from "react";
4 | import axios from "axios";
5 | import { Button } from "@/components/ui/button";
6 | import { useToast } from "@/hooks/use-toast";
7 | import { formatDistanceToNow } from "date-fns";
8 | import Image from "next/image";
9 | import { Loader2 } from "lucide-react";
10 |
11 | const UploadImageAndShareLink = () => {
12 | const [files, setFiles] = useState(null);
13 | const [loadingUpload, setLoadingUpload] = useState(false);
14 | const [uploadedImageUrl, setUploadedImageUrl] = useState("");
15 | const { toast } = useToast();
16 |
17 | const handleFileChange = (files: File) => {
18 | setFiles(files);
19 | // console.log(files);
20 | };
21 |
22 | const handleUploadFile = async () => {
23 | if (files?.size === 0) {
24 | toast({
25 | title: "Empty File or File size is Zero.",
26 | duration: 2000,
27 | description: formatDistanceToNow(new Date(new Date()), {
28 | addSuffix: true,
29 | }),
30 | });
31 | return;
32 | }
33 | setLoadingUpload(true);
34 | try {
35 | const formData = new FormData();
36 | formData.append("file", files);
37 | const getImageRes = await axios.post("/api/ImageUploadForLink", formData, {
38 | headers: {
39 | "Content-Type": "multipart/form-data",
40 | },
41 | });
42 |
43 | if (getImageRes.data.status === false) {
44 | throw new Error(getImageRes.data.message);
45 | }
46 |
47 | // console.log(getImageRes);
48 | setUploadedImageUrl(getImageRes.data.imageUrl);
49 | } catch (error) {
50 | toast({
51 | title: "Uploading File failed",
52 | description: formatDistanceToNow(new Date(new Date()), {
53 | addSuffix: true,
54 | }),
55 | });
56 | } finally {
57 | setLoadingUpload(false);
58 | }
59 | };
60 |
61 | const handleCopyImage = () => {
62 | navigator.clipboard.writeText(uploadedImageUrl!);
63 | toast({
64 | title: "Link Copied Successfully",
65 | duration: 2000,
66 | description: formatDistanceToNow(new Date(new Date()), {
67 | addSuffix: true,
68 | }),
69 | });
70 | };
71 |
72 | if (loadingUpload) {
73 | return (
74 |
75 |
76 |
77 | );
78 | }
79 | return (
80 |
81 | {!uploadedImageUrl ? (
82 | <>
83 |
84 |
85 | >
86 | ) : (
87 |
88 |
95 |
96 |
97 | )}
98 |
99 | );
100 | };
101 |
102 | export default UploadImageAndShareLink;
103 |
--------------------------------------------------------------------------------
/src/app/explore/page.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { ExploreCard, propTypes } from "./_components/ExploreCards";
3 |
4 | const data = [
5 | {
6 | title: "Generate Image Link",
7 | description: "Upload an image, get the link, and use it anywhere.",
8 | path: "/explore/imageUpload",
9 | mainImage:
10 | "http://res.cloudinary.com/dakddv1pm/image/upload/v1737197135/posts/qjwllc7qqilrfc33600s.jpg",
11 | },
12 | {
13 | title: "Bug Tracker",
14 | description: "Track the Progess of bug hunting and resolve it.",
15 | path: "/explore/bugtracker",
16 |
17 | mainImage:
18 | "http://res.cloudinary.com/dakddv1pm/image/upload/v1737197037/posts/spuzbvkdy5mqsk7lr63e.jpg",
19 | },
20 |
21 | {
22 | title: "Code Editor",
23 | description: "Live Code with teh feature of videocall.",
24 | path: "/explore/code-editor",
25 |
26 | mainImage:
27 | "http://res.cloudinary.com/dakddv1pm/image/upload/v1742798637/posts/kaa9rere8hvucndpzxxu.jpg",
28 | },
29 |
30 |
31 | {
32 | title: "Shyllido",
33 | description: "Convert your prompt into an image with the help of AI.",
34 | path: "/explore/image-generator",
35 |
36 | mainImage:
37 | "http://res.cloudinary.com/dakddv1pm/image/upload/v1742802688/posts/zrkfbuhbbwxjgfwj6fj7.webp",
38 | },
39 | ];
40 |
41 |
42 | const Explore = () => {
43 | return (
44 |
45 | {data.map((d: propTypes, index: number) => (
46 |
53 | ))}
54 |
55 | );
56 | };
57 |
58 | export default Explore;
59 |
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iutkarsh077/Snippets-SAAS-Production/fcc957b6898a12e52f68c9de38d83f72b4a49944/src/app/favicon.ico
--------------------------------------------------------------------------------
/src/app/feeds/_components/Comment.tsx:
--------------------------------------------------------------------------------
1 | import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
2 | import { CircleX } from "lucide-react";
3 | import Link from "next/link";
4 |
5 | interface AuthorProp {
6 | id: string;
7 | username: string;
8 | profileImage: string;
9 | }
10 |
11 | interface feedAuthor {
12 | authorId: string;
13 | }
14 |
15 | interface CommentProps {
16 | content: string;
17 | author: AuthorProp;
18 | onDelete?: () => void;
19 | userId: string;
20 | feed: feedAuthor;
21 | }
22 |
23 | export function Comment({
24 | author,
25 | content,
26 | onDelete,
27 | userId,
28 | feed,
29 | }: CommentProps) {
30 | const canDelete = userId === author.id || userId === feed?.authorId;
31 | return (
32 |
33 |
34 |
35 |
36 |
37 | {author.username[0].toUpperCase()}
38 |
39 |
40 |
41 | {author.username}
42 |
43 |
44 | {content}
45 |
46 |
47 |
48 |
49 |
50 | {canDelete && (
51 |
58 | )}
59 |
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/src/app/feeds/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useEffect, useState } from "react";
3 | import ImageCard, { ImageCardProps } from "./_components/HeaderImageCard";
4 | import { GetLatestFeed } from "../../../actions/GetLatestFeed";
5 | import { Loader2 } from "lucide-react";
6 | import { DeleteFeed } from "../../../actions/DeleteFeed";
7 | import { useToast } from "@/hooks/use-toast";
8 |
9 | const Feed = () => {
10 | const [cardData, setCardData] = useState(null);
11 | const [loading, setLoading] = useState(false);
12 | const { toast } = useToast();
13 |
14 |
15 | useEffect(() => {
16 | const fetchFeedData = async () => {
17 | try {
18 | setLoading(true);
19 | const res = await GetLatestFeed();
20 | if (res.status === false) {
21 | throw new Error(res.msg);
22 | }
23 | // console.log(res);
24 | setCardData(res?.feedsData);
25 | } catch (error) {
26 | // console.log(error);
27 | } finally {
28 | setLoading(false);
29 | }
30 | };
31 | fetchFeedData();
32 | }, []);
33 |
34 | const handleDeleteFeed = async (feedId: string) => {
35 | try {
36 | setCardData((prevData: any) =>
37 | prevData ? prevData.filter((feed: any) => feed.id !== feedId) : prevData
38 | );
39 | const res = await DeleteFeed(feedId);
40 | if (res.status === false) {
41 | throw new Error(res.msg);
42 | }
43 | toast({
44 | title: "Feed deleted successfully.",
45 | duration: 2000,
46 | });
47 | } catch (error) {
48 | // console.log(error);
49 | toast({
50 | title: "failed to delete feeds.",
51 | duration: 2000,
52 | });
53 | }
54 | };
55 |
56 | if (loading) {
57 | return (
58 |
59 |
60 |
61 | );
62 | }
63 |
64 | return (
65 |
66 |
67 | {cardData?.map((cardDataItems: ImageCardProps, index: number) => (
68 |
69 |
73 |
74 | ))}
75 |
76 |
77 |
78 | );
79 | };
80 |
81 | export default Feed;
82 |
--------------------------------------------------------------------------------
/src/app/fonts/GeistMonoVF.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iutkarsh077/Snippets-SAAS-Production/fcc957b6898a12e52f68c9de38d83f72b4a49944/src/app/fonts/GeistMonoVF.woff
--------------------------------------------------------------------------------
/src/app/fonts/GeistVF.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iutkarsh077/Snippets-SAAS-Production/fcc957b6898a12e52f68c9de38d83f72b4a49944/src/app/fonts/GeistVF.woff
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | .example {
6 | overflow: -moz-scrollbars-none; /* Firefox */
7 | -ms-overflow-style: none; /* Internet Explorer 10+ */
8 | scrollbar-width: none; /* Firefox */
9 | overflow: auto; /* Scrollable */
10 | }
11 |
12 | .example::-webkit-scrollbar {
13 | display: none; /* WebKit browsers */
14 | }
15 |
16 | @layer base {
17 | :root {
18 | --background: 0 0% 100%;
19 | --foreground: 240 10% 3.9%;
20 | --card: 0 0% 100%;
21 | --card-foreground: 240 10% 3.9%;
22 | --popover: 0 0% 100%;
23 | --popover-foreground: 240 10% 3.9%;
24 | --primary: 240 5.9% 10%;
25 | --primary-foreground: 0 0% 98%;
26 | --secondary: 240 4.8% 95.9%;
27 | --secondary-foreground: 240 5.9% 10%;
28 | --muted: 240 4.8% 95.9%;
29 | --muted-foreground: 240 3.8% 46.1%;
30 | --accent: 240 4.8% 95.9%;
31 | --accent-foreground: 240 5.9% 10%;
32 | --destructive: 0 84.2% 60.2%;
33 | --destructive-foreground: 0 0% 98%;
34 | --border: 240 5.9% 90%;
35 | --input: 240 5.9% 90%;
36 | --ring: 240 10% 3.9%;
37 | --chart-1: 12 76% 61%;
38 | --chart-2: 173 58% 39%;
39 | --chart-3: 197 37% 24%;
40 | --chart-4: 43 74% 66%;
41 | --chart-5: 27 87% 67%;
42 | --radius: 0.5rem
43 | }
44 | .dark {
45 | --background: 240 10% 3.9%;
46 | --foreground: 0 0% 98%;
47 | --card: 240 10% 3.9%;
48 | --card-foreground: 0 0% 98%;
49 | --popover: 240 10% 3.9%;
50 | --popover-foreground: 0 0% 98%;
51 | --primary: 0 0% 98%;
52 | --primary-foreground: 240 5.9% 10%;
53 | --secondary: 240 3.7% 15.9%;
54 | --secondary-foreground: 0 0% 98%;
55 | --muted: 240 3.7% 15.9%;
56 | --muted-foreground: 240 5% 64.9%;
57 | --accent: 240 3.7% 15.9%;
58 | --accent-foreground: 0 0% 98%;
59 | --destructive: 0 62.8% 30.6%;
60 | --destructive-foreground: 0 0% 98%;
61 | --border: 240 3.7% 15.9%;
62 | --input: 240 3.7% 15.9%;
63 | --ring: 240 4.9% 83.9%;
64 | --chart-1: 220 70% 50%;
65 | --chart-2: 160 60% 45%;
66 | --chart-3: 30 80% 55%;
67 | --chart-4: 280 65% 60%;
68 | --chart-5: 340 75% 55%
69 | }
70 | }
71 |
72 | @layer base {
73 | * {
74 | @apply border-border;
75 | }
76 | body {
77 | @apply bg-background text-foreground;
78 | }
79 | }
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import "./globals.css";
3 | import { NextThemeProvider } from "@/components/NextUItheme";
4 | import Navbar from "@/components/Navbar";
5 | import { Toaster } from "@/components/ui/toaster";
6 | import { Poppins } from "next/font/google";
7 | import Script from "next/script";
8 |
9 | const poppinsFont = Poppins({
10 | subsets: ["latin"],
11 | weight: "500",
12 | });
13 |
14 | export const metadata: Metadata = {
15 | title: "Snippets - Empowering Developers with Sharable Code Solutions",
16 | description:
17 | "Discover, share, and collaborate on code snippets in a thriving community of developers. Snippets offers a platform to save your best ideas, learn from others, and contribute to the ever-growing knowledge base of programming expertise.",
18 | openGraph: {
19 | images: "https://i.postimg.cc/c1hMgQ7P/snippet-1.png",
20 | },
21 | };
22 |
23 | export default function RootLayout({
24 | children,
25 | }: Readonly<{
26 | children: React.ReactNode;
27 | }>) {
28 | return (
29 |
30 |
31 |
34 |
38 |
46 |
47 | {children}
48 |
49 |
50 |
51 |
52 | );
53 | }
54 |
--------------------------------------------------------------------------------
/src/app/not-found.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 |
3 | export default function NotFound() {
4 | return (
5 |
6 |
7 |
404
8 |
Page Not Found
9 |
The page you're looking for doesn't exist or has been moved.
10 |
14 | Go Home
15 |
16 |
17 |
18 | )
19 | }
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import HomeSection from "./(home)/_components/Home";
3 |
4 | const Home = () => {
5 | return ;
6 | };
7 |
8 | export default Home;
9 |
--------------------------------------------------------------------------------
/src/app/sendMsg/[username]/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useParams, useRouter } from "next/navigation";
3 | import { useState } from "react";
4 | import { motion } from "framer-motion";
5 | import { Loader2, Send } from "lucide-react";
6 | import React from "react";
7 | import { SaveAndSendMessage } from "../../../../actions/SaveAndSendMessage";
8 | import { useToast } from "@/hooks/use-toast";
9 | import { formatDistanceToNow } from "date-fns";
10 |
11 | const SendMsgToAnotherUser = () => {
12 | const { username } = useParams();
13 | const [question, setQuestion] = useState("");
14 | const [loading, setLoading] = useState(false);
15 | const { toast } = useToast();
16 | const router = useRouter();
17 |
18 | const handleSubmit = async (e: any) => {
19 | if (question.length === 0) return;
20 | e.preventDefault();
21 | setLoading(true);
22 | try {
23 | const data = {
24 | receiverUsername: username,
25 | text: question,
26 | };
27 | const res = await SaveAndSendMessage(data as any);
28 |
29 | if (res.status === false) {
30 | throw new Error(res.msg);
31 | }
32 | toast({
33 | title: "Scheduled: Catch up",
34 | description: formatDistanceToNow(new Date(new Date()), {
35 | addSuffix: true,
36 | }),
37 | });
38 | setQuestion("");
39 | router.push("/userChat")
40 | } catch (error) {
41 | // console.log(error);
42 | } finally {
43 | setLoading(false);
44 | }
45 | };
46 |
47 | return (
48 |
54 |
60 | Send a message to {username}
61 |
62 |
98 |
99 | );
100 | };
101 |
102 | export default SendMsgToAnotherUser;
103 |
--------------------------------------------------------------------------------
/src/app/snippets/_components/CodeCard.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { motion } from "framer-motion";
3 | import { Clipboard, Check } from "lucide-react";
4 | import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
5 | import { atomDark } from "react-syntax-highlighter/dist/esm/styles/prism";
6 | import Link from "next/link";
7 |
8 | export default function CodeCard({ snippet }: any) {
9 | const [copied, setCopied] = useState(false);
10 |
11 | const copyToClipboard = () => {
12 | navigator.clipboard.writeText(snippet.code);
13 | setCopied(true);
14 | setTimeout(() => setCopied(false), 2000);
15 | };
16 |
17 | const truncate = (text: string, length: number) => {
18 | if (text.length <= length) {
19 | return text;
20 | }
21 | return text.slice(0, length) + "...";
22 | };
23 |
24 | const truncatedCode = truncate(snippet.code.trim(), 300);
25 | return (
26 | <>
27 |
34 |
35 |
36 |
41 |
47 | {copied ? : }
48 |
49 |
50 |
51 |
64 | {truncatedCode}
65 |
66 |
67 |
68 |
74 |
75 | {snippet.programmingLanguage}
76 |
77 |
78 | {snippet.code.split("\n").length}
79 |
80 |
81 |
82 | >
83 | );
84 | }
85 |
--------------------------------------------------------------------------------
/src/app/snippets/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useEffect, useState } from "react";
3 | import CodeCard from "./_components/CodeCard";
4 | import { Loader2 } from "lucide-react";
5 | import { GetAllSnippets } from "../../../actions/GetAllSnippets";
6 |
7 | export interface SnippetType {
8 | id: string;
9 | programmingLanguage: string;
10 | code: string;
11 | question: string;
12 | authorId: string;
13 | createdAt: string;
14 | updatedAt: string;
15 | }
16 |
17 | const MainSnippets = () => {
18 | const [snippets, setSnippets] = useState(null);
19 | const [loading, setLoading] = useState(false);
20 |
21 | useEffect(() => {
22 | const getAllSnippets = async () => {
23 | setLoading(true);
24 | const res = await GetAllSnippets();
25 | if (res && res.data) {
26 | setSnippets(res.data as any);
27 | // console.log(res);
28 | }
29 | setLoading(false);
30 | };
31 | getAllSnippets();
32 | }, []);
33 |
34 | if (loading) {
35 | return (
36 |
37 |
38 |
39 | );
40 | }
41 |
42 | return (
43 |
44 | {snippets &&
45 | snippets
46 | .sort((a: { createdAt: any }, b: { createdAt: any }) => {
47 | return (
48 | new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
49 | );
50 | })
51 | .map((snippet: any, index: number) => (
52 |
53 |
54 |
55 | ))}
56 |
57 | );
58 | };
59 |
60 | export default MainSnippets;
61 |
--------------------------------------------------------------------------------
/src/app/uploadSnippets/_components/DescriptionForUpload.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useState } from "react";
3 | import { motion } from "framer-motion";
4 | import { Send } from "lucide-react";
5 | import { toast, ToastContainer } from "react-toastify";
6 | import { UploadSnippets } from "../../../../actions/uploadSnippets";
7 | import { useRouter } from "next/navigation";
8 | export default function DescriptionBox({
9 | setDescription,
10 | language,
11 | code,
12 | }: {
13 | setDescription: any;
14 | language: string;
15 | code: string;
16 | }) {
17 | const [question, setQuestion] = useState("");
18 | const router = useRouter();
19 | const handleSubmit = async (e: any) => {
20 | if (question.length === 0) return;
21 | e.preventDefault();
22 | const data = {
23 | code,
24 | language,
25 | question,
26 | };
27 | try {
28 | const res = await UploadSnippets(data);
29 | // console.log(res);
30 | if (res.status === false) {
31 | throw new Error(res.msg);
32 | }
33 | router.push("/snippets");
34 | } catch (error) {
35 | // console.log(error);
36 | }
37 | };
38 |
39 | return (
40 |
46 |
47 |
53 | Ask a Question
54 |
55 |
88 |
89 | );
90 | }
91 |
--------------------------------------------------------------------------------
/src/app/uploadSnippets/_components/Searchlanguage.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { motion, AnimatePresence } from "framer-motion";
3 | import { programmingLanguages as languages } from "@/lib/LanguageData";
4 | import { Search, ChevronDown, ArrowRight } from "lucide-react";
5 |
6 | export default function SearchLanguage({
7 | lang,
8 | setLang,
9 | setShowSearchLanguage,
10 | setshowDescriptionBox,
11 | }: {
12 | lang: string,
13 | setLang: any;
14 | setShowSearchLanguage: any;
15 | setshowDescriptionBox: any;
16 | }) {
17 | const [searchTerm, setSearchTerm] = useState("");
18 | const [isOpen, setIsOpen] = useState(false);
19 | const filteredLanguages = languages.filter((lang) =>
20 | lang.toLowerCase().includes(searchTerm.toLowerCase())
21 | );
22 |
23 | const handleSubmit = () => {
24 | if(lang.length === 0) return;
25 | setShowSearchLanguage(false);
26 | setshowDescriptionBox(true);
27 | };
28 |
29 | return (
30 |
31 |
32 |
38 | setSearchTerm(e.target.value)}
43 | className="w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
44 | />
45 |
46 |
47 |
setIsOpen(!isOpen)}
51 | className="mt-2 w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent flex justify-between items-center"
52 | >
53 |
54 | {filteredLanguages.length > 0
55 | ? filteredLanguages[0]
56 | : "No languages found"}
57 |
58 |
63 |
64 |
65 | {isOpen && (
66 |
73 | {filteredLanguages.map((language, index) => (
74 | {
79 | setSearchTerm(language);
80 | setIsOpen(false);
81 | setLang(language);
82 | }}
83 | >
84 | {language}
85 |
86 | ))}
87 |
88 | )}
89 |
104 | Next
105 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | );
122 | }
123 |
--------------------------------------------------------------------------------
/src/app/uploadSnippets/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useState } from "react";
3 | import CodeCard from "./_components/CodeInput";
4 | import SearchLanguage from "./_components/Searchlanguage";
5 |
6 | import DescriptionBox from "./_components/DescriptionForUpload";
7 |
8 | const UploadSnippets = () => {
9 | const [lang, setLang] = useState("");
10 | const [code, setCode] = useState("")
11 | const [description, setDescription] = useState("");
12 | const [showCodeCard, setShowCodeCard] = useState(true);
13 | const [showSearchLanguage, setShowSearchLanguage] = useState(false);
14 | const [showDescriptionBox, setshowDescriptionBox] = useState(false);
15 |
16 | return (
17 |
23 | )
24 | }
25 |
26 | export default UploadSnippets
27 |
--------------------------------------------------------------------------------
/src/components/NextUItheme.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import {NextUIProvider} from '@nextui-org/react'
3 | import {ThemeProvider as NextThemesProvider} from "next-themes";
4 |
5 | export function NextThemeProvider({children}: { children: React.ReactNode }) {
6 | return (
7 |
8 |
9 | {children}
10 |
11 |
12 | )
13 | }
--------------------------------------------------------------------------------
/src/components/Toggle/MoonIcon.tsx:
--------------------------------------------------------------------------------
1 | export const MoonIcon = (props: any) => (
2 |
18 | );
--------------------------------------------------------------------------------
/src/components/Toggle/SunIcon.tsx:
--------------------------------------------------------------------------------
1 | export const SunIcon = (props: any) => (
2 |
17 | );
--------------------------------------------------------------------------------
/src/components/Toggle/Switch.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { Switch } from "@nextui-org/react";
3 | import { MoonIcon } from "./MoonIcon";
4 | import { SunIcon } from "./SunIcon";
5 | import { useTheme } from "next-themes";
6 | import { useEffect, useState } from "react";
7 |
8 | export default function SwitchToggle() {
9 | const [mounted, setMounted] = useState(false);
10 | const { theme, setTheme } = useTheme();
11 |
12 |
13 | useEffect(() => {
14 | setMounted(true);
15 | }, []);
16 |
17 | if (!mounted) return null;
18 | const handleThemes = () => {
19 | if (theme === "dark") {
20 | setTheme("light");
21 | } else {
22 | setTheme("dark");
23 | }
24 | };
25 | return (
26 |
32 | isSelected ? (
33 |
34 | ) : (
35 |
36 | )
37 | }
38 | >
39 | );
40 | }
--------------------------------------------------------------------------------
/src/components/avatar.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as AvatarPrimitive from "@radix-ui/react-avatar"
3 |
4 | import { cn } from "../lib/utils"
5 |
6 |
7 |
8 | const Avatar = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ))
21 | Avatar.displayName = AvatarPrimitive.Root.displayName
22 |
23 | const AvatarImage = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, ...props }, ref) => (
27 |
32 | ))
33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName
34 |
35 | const AvatarFallback = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 | ))
48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49 |
50 | export { Avatar, AvatarImage, AvatarFallback }
51 |
--------------------------------------------------------------------------------
/src/components/card-hover-effect.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from "../lib/utils";
2 | import { AnimatePresence, motion } from "framer-motion";
3 | import Link from "next/link";
4 | import { useState } from "react";
5 |
6 | export const HoverEffect = ({
7 | items,
8 | className,
9 | }: {
10 | items: {
11 | title: string;
12 | description: string;
13 | link: string;
14 | }[];
15 | className?: string;
16 | }) => {
17 | const [hoveredIndex, setHoveredIndex] = useState(null);
18 |
19 | return (
20 |
26 | {items.map((item, idx) => (
27 |
setHoveredIndex(idx)}
32 | onMouseLeave={() => setHoveredIndex(null)}
33 | >
34 |
35 | {hoveredIndex === idx && (
36 |
49 | )}
50 |
51 |
52 | {item.title}
53 | {item.description}
54 |
55 |
56 | ))}
57 |
58 | );
59 | };
60 |
61 | export const Card = ({
62 | className,
63 | children,
64 | }: {
65 | className?: string;
66 | children: React.ReactNode;
67 | }) => {
68 | return (
69 |
79 | );
80 | };
81 | export const CardTitle = ({
82 | className,
83 | children,
84 | }: {
85 | className?: string;
86 | children: React.ReactNode;
87 | }) => {
88 | return (
89 |
90 | {children}
91 |
92 | );
93 | };
94 | export const CardDescription = ({
95 | className,
96 | children,
97 | }: {
98 | className?: string;
99 | children: React.ReactNode;
100 | }) => {
101 | return (
102 |
108 | {children}
109 |
110 | );
111 | };
112 |
--------------------------------------------------------------------------------
/src/components/card.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "../lib/utils"
4 |
5 | const Card = React.forwardRef<
6 | HTMLDivElement,
7 | React.HTMLAttributes
8 | >(({ className, ...props }, ref) => (
9 |
17 | ))
18 | Card.displayName = "Card"
19 |
20 | const CardHeader = React.forwardRef<
21 | HTMLDivElement,
22 | React.HTMLAttributes
23 | >(({ className, ...props }, ref) => (
24 |
29 | ))
30 | CardHeader.displayName = "CardHeader"
31 |
32 | const CardTitle = React.forwardRef<
33 | HTMLParagraphElement,
34 | React.HTMLAttributes
35 | >(({ className, ...props }, ref) => (
36 |
41 | ))
42 | CardTitle.displayName = "CardTitle"
43 |
44 | const CardDescription = React.forwardRef<
45 | HTMLParagraphElement,
46 | React.HTMLAttributes
47 | >(({ className, ...props }, ref) => (
48 |
53 | ))
54 | CardDescription.displayName = "CardDescription"
55 |
56 | const CardContent = React.forwardRef<
57 | HTMLDivElement,
58 | React.HTMLAttributes
59 | >(({ className, ...props }, ref) => (
60 |
61 | ))
62 | CardContent.displayName = "CardContent"
63 |
64 | const CardFooter = React.forwardRef<
65 | HTMLDivElement,
66 | React.HTMLAttributes
67 | >(({ className, ...props }, ref) => (
68 |
73 | ))
74 | CardFooter.displayName = "CardFooter"
75 |
76 | export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
77 |
--------------------------------------------------------------------------------
/src/components/container-scroll-animation.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef } from "react";
2 | import { useScroll, useTransform, motion, MotionValue } from "framer-motion";
3 |
4 | export const ContainerScroll = ({
5 | titleComponent,
6 | children,
7 | }: {
8 | titleComponent: string | React.ReactNode;
9 | children: React.ReactNode;
10 | }) => {
11 | const containerRef = useRef(null);
12 | const { scrollYProgress } = useScroll({
13 | target: containerRef,
14 | });
15 | const [isMobile, setIsMobile] = React.useState(false);
16 |
17 | React.useEffect(() => {
18 | const checkMobile = () => {
19 | setIsMobile(window.innerWidth <= 768);
20 | };
21 | checkMobile();
22 | window.addEventListener("resize", checkMobile);
23 | return () => {
24 | window.removeEventListener("resize", checkMobile);
25 | };
26 | }, []);
27 |
28 | const scaleDimensions = () => {
29 | return isMobile ? [0.7, 0.9] : [1.05, 1];
30 | };
31 |
32 | const rotate = useTransform(scrollYProgress, [0, 1], [20, 0]);
33 | const scale = useTransform(scrollYProgress, [0, 1], scaleDimensions());
34 | const translate = useTransform(scrollYProgress, [0, 1], [0, -100]);
35 |
36 | return (
37 |
41 |
47 |
48 |
49 | {children}
50 |
51 |
52 |
53 | );
54 | };
55 |
56 | export const Header = ({ translate, titleComponent }: any) => {
57 | return (
58 |
64 | {titleComponent}
65 |
66 | );
67 | };
68 |
69 | export const Card = ({
70 | rotate,
71 | scale,
72 | children,
73 | }: {
74 | rotate: MotionValue;
75 | scale: MotionValue;
76 | translate: MotionValue;
77 | children: React.ReactNode;
78 | }) => {
79 | return (
80 |
89 |
90 | {children}
91 |
92 |
93 | );
94 | };
95 |
--------------------------------------------------------------------------------
/src/components/separator.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as SeparatorPrimitive from "@radix-ui/react-separator"
3 |
4 | import { cn } from "../lib/utils"
5 |
6 | const Separator = React.forwardRef<
7 | React.ElementRef,
8 | React.ComponentPropsWithoutRef
9 | >(
10 | (
11 | { className, orientation = "horizontal", decorative = true, ...props },
12 | ref
13 | ) => (
14 |
25 | )
26 | )
27 | Separator.displayName = SeparatorPrimitive.Root.displayName
28 |
29 | export { Separator }
30 |
--------------------------------------------------------------------------------
/src/components/text-generate-effect.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { motion, stagger, useAnimate } from "framer-motion";
3 | import { cn } from "../lib/utils";
4 |
5 | export const TextGenerateEffect = ({
6 | words,
7 | className,
8 | filter = true,
9 | duration = 0.01,
10 | }: {
11 | words: string;
12 | className?: string;
13 | filter?: boolean;
14 | duration?: number;
15 | }) => {
16 | const [scope, animate] = useAnimate();
17 | const wordsArray = words.split(" ");
18 | useEffect(() => {
19 | animate(
20 | "span",
21 | {
22 | opacity: 1,
23 | filter: filter ? "blur(0px)" : "none",
24 | },
25 | {
26 | duration: duration ? duration : 1,
27 | delay: stagger(0.01),
28 | }
29 | );
30 | }, [scope.current]);
31 |
32 | const renderWords = () => {
33 | return (
34 |
35 | {wordsArray.map((word, idx) => {
36 | return (
37 |
44 | {word}{" "}
45 |
46 | );
47 | })}
48 |
49 | );
50 | };
51 |
52 | return (
53 |
54 |
55 |
56 | {renderWords()}
57 |
58 |
59 |
60 | );
61 | };
62 |
--------------------------------------------------------------------------------
/src/components/ui/3d-card.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { cn } from "@/lib/utils";
4 | import Image from "next/image";
5 | import React, {
6 | createContext,
7 | useState,
8 | useContext,
9 | useRef,
10 | useEffect,
11 | } from "react";
12 |
13 | const MouseEnterContext = createContext<
14 | [boolean, React.Dispatch>] | undefined
15 | >(undefined);
16 |
17 | export const CardContainer = ({
18 | children,
19 | className,
20 | containerClassName,
21 | }: {
22 | children?: React.ReactNode;
23 | className?: string;
24 | containerClassName?: string;
25 | }) => {
26 | const containerRef = useRef(null);
27 | const [isMouseEntered, setIsMouseEntered] = useState(false);
28 |
29 | const handleMouseMove = (e: React.MouseEvent) => {
30 | if (!containerRef.current) return;
31 | const { left, top, width, height } =
32 | containerRef.current.getBoundingClientRect();
33 | const x = (e.clientX - left - width / 2) / 25;
34 | const y = (e.clientY - top - height / 2) / 25;
35 | containerRef.current.style.transform = `rotateY(${x}deg) rotateX(${y}deg)`;
36 | };
37 |
38 | const handleMouseEnter = (e: React.MouseEvent) => {
39 | setIsMouseEntered(true);
40 | if (!containerRef.current) return;
41 | };
42 |
43 | const handleMouseLeave = (e: React.MouseEvent) => {
44 | if (!containerRef.current) return;
45 | setIsMouseEntered(false);
46 | containerRef.current.style.transform = `rotateY(0deg) rotateX(0deg)`;
47 | };
48 | return (
49 |
50 |
59 |
72 | {children}
73 |
74 |
75 |
76 | );
77 | };
78 |
79 | export const CardBody = ({
80 | children,
81 | className,
82 | }: {
83 | children: React.ReactNode;
84 | className?: string;
85 | }) => {
86 | return (
87 | *]:[transform-style:preserve-3d]",
90 | className
91 | )}
92 | >
93 | {children}
94 |
95 | );
96 | };
97 |
98 | export const CardItem = ({
99 | as: Tag = "div",
100 | children,
101 | className,
102 | translateX = 0,
103 | translateY = 0,
104 | translateZ = 0,
105 | rotateX = 0,
106 | rotateY = 0,
107 | rotateZ = 0,
108 | ...rest
109 | }: {
110 | as?: React.ElementType;
111 | children: React.ReactNode;
112 | className?: string;
113 | translateX?: number | string;
114 | translateY?: number | string;
115 | translateZ?: number | string;
116 | rotateX?: number | string;
117 | rotateY?: number | string;
118 | rotateZ?: number | string;
119 | [key: string]: any;
120 | }) => {
121 | const ref = useRef(null);
122 | const [isMouseEntered] = useMouseEnter();
123 |
124 | useEffect(() => {
125 | handleAnimations();
126 | }, [isMouseEntered]);
127 |
128 | const handleAnimations = () => {
129 | if (!ref.current) return;
130 | if (isMouseEntered) {
131 | ref.current.style.transform = `translateX(${translateX}px) translateY(${translateY}px) translateZ(${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`;
132 | } else {
133 | ref.current.style.transform = `translateX(0px) translateY(0px) translateZ(0px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)`;
134 | }
135 | };
136 |
137 | return (
138 |
143 | {children}
144 |
145 | );
146 | };
147 |
148 | // Create a hook to use the context
149 | export const useMouseEnter = () => {
150 | const context = useContext(MouseEnterContext);
151 | if (context === undefined) {
152 | throw new Error("useMouseEnter must be used within a MouseEnterProvider");
153 | }
154 | return context;
155 | };
156 |
--------------------------------------------------------------------------------
/src/components/ui/alert.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { cva, type VariantProps } from "class-variance-authority"
3 |
4 | import { cn } from "@/lib/utils"
5 |
6 | const alertVariants = cva(
7 | "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
8 | {
9 | variants: {
10 | variant: {
11 | default: "bg-background text-foreground",
12 | destructive:
13 | "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
14 | },
15 | },
16 | defaultVariants: {
17 | variant: "default",
18 | },
19 | }
20 | )
21 |
22 | const Alert = React.forwardRef<
23 | HTMLDivElement,
24 | React.HTMLAttributes & VariantProps
25 | >(({ className, variant, ...props }, ref) => (
26 |
32 | ))
33 | Alert.displayName = "Alert"
34 |
35 | const AlertTitle = React.forwardRef<
36 | HTMLParagraphElement,
37 | React.HTMLAttributes
38 | >(({ className, ...props }, ref) => (
39 |
44 | ))
45 | AlertTitle.displayName = "AlertTitle"
46 |
47 | const AlertDescription = React.forwardRef<
48 | HTMLParagraphElement,
49 | React.HTMLAttributes
50 | >(({ className, ...props }, ref) => (
51 |
56 | ))
57 | AlertDescription.displayName = "AlertDescription"
58 |
59 | export { Alert, AlertTitle, AlertDescription }
60 |
--------------------------------------------------------------------------------
/src/components/ui/avatar.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AvatarPrimitive from "@radix-ui/react-avatar"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Avatar = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ))
21 | Avatar.displayName = AvatarPrimitive.Root.displayName
22 |
23 | const AvatarImage = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, ...props }, ref) => (
27 |
32 | ))
33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName
34 |
35 | const AvatarFallback = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 | ))
48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49 |
50 | export { Avatar, AvatarImage, AvatarFallback }
51 |
--------------------------------------------------------------------------------
/src/components/ui/badge.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { cva, type VariantProps } from "class-variance-authority"
3 |
4 | import { cn } from "@/lib/utils"
5 |
6 | const badgeVariants = cva(
7 | "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8 | {
9 | variants: {
10 | variant: {
11 | default:
12 | "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
13 | secondary:
14 | "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15 | destructive:
16 | "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
17 | outline: "text-foreground",
18 | },
19 | },
20 | defaultVariants: {
21 | variant: "default",
22 | },
23 | }
24 | )
25 |
26 | export interface BadgeProps
27 | extends React.HTMLAttributes,
28 | VariantProps {}
29 |
30 | function Badge({ className, variant, ...props }: BadgeProps) {
31 | return (
32 |
33 | )
34 | }
35 |
36 | export { Badge, badgeVariants }
37 |
--------------------------------------------------------------------------------
/src/components/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { Slot } from "@radix-ui/react-slot"
3 | import { cva, type VariantProps } from "class-variance-authority"
4 |
5 | import { cn } from "@/lib/utils"
6 |
7 | const buttonVariants = cva(
8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9 | {
10 | variants: {
11 | variant: {
12 | default:
13 | "bg-primary text-primary-foreground shadow hover:bg-primary/90",
14 | destructive:
15 | "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
16 | outline:
17 | "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
18 | secondary:
19 | "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
20 | ghost: "hover:bg-accent hover:text-accent-foreground",
21 | link: "text-primary underline-offset-4 hover:underline",
22 | },
23 | size: {
24 | default: "h-9 px-4 py-2",
25 | sm: "h-8 rounded-md px-3 text-xs",
26 | lg: "h-10 rounded-md px-8",
27 | icon: "h-9 w-9",
28 | },
29 | },
30 | defaultVariants: {
31 | variant: "default",
32 | size: "default",
33 | },
34 | }
35 | )
36 |
37 | export interface ButtonProps
38 | extends React.ButtonHTMLAttributes,
39 | VariantProps {
40 | asChild?: boolean
41 | }
42 |
43 | const Button = React.forwardRef(
44 | ({ className, variant, size, asChild = false, ...props }, ref) => {
45 | const Comp = asChild ? Slot : "button"
46 | return (
47 |
52 | )
53 | }
54 | )
55 | Button.displayName = "Button"
56 |
57 | export { Button, buttonVariants }
58 |
--------------------------------------------------------------------------------
/src/components/ui/card.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | const Card = React.forwardRef<
6 | HTMLDivElement,
7 | React.HTMLAttributes
8 | >(({ className, ...props }, ref) => (
9 |
17 | ))
18 | Card.displayName = "Card"
19 |
20 | const CardHeader = React.forwardRef<
21 | HTMLDivElement,
22 | React.HTMLAttributes
23 | >(({ className, ...props }, ref) => (
24 |
29 | ))
30 | CardHeader.displayName = "CardHeader"
31 |
32 | const CardTitle = React.forwardRef<
33 | HTMLParagraphElement,
34 | React.HTMLAttributes
35 | >(({ className, ...props }, ref) => (
36 |
41 | ))
42 | CardTitle.displayName = "CardTitle"
43 |
44 | const CardDescription = React.forwardRef<
45 | HTMLParagraphElement,
46 | React.HTMLAttributes
47 | >(({ className, ...props }, ref) => (
48 |
53 | ))
54 | CardDescription.displayName = "CardDescription"
55 |
56 | const CardContent = React.forwardRef<
57 | HTMLDivElement,
58 | React.HTMLAttributes
59 | >(({ className, ...props }, ref) => (
60 |
61 | ))
62 | CardContent.displayName = "CardContent"
63 |
64 | const CardFooter = React.forwardRef<
65 | HTMLDivElement,
66 | React.HTMLAttributes
67 | >(({ className, ...props }, ref) => (
68 |
73 | ))
74 | CardFooter.displayName = "CardFooter"
75 |
76 | export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
77 |
--------------------------------------------------------------------------------
/src/components/ui/checkbox.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
5 | import { cn } from "@/lib/utils"
6 | import { CheckIcon } from "@radix-ui/react-icons"
7 |
8 | const Checkbox = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 |
23 |
24 |
25 |
26 | ))
27 | Checkbox.displayName = CheckboxPrimitive.Root.displayName
28 |
29 | export { Checkbox }
30 |
--------------------------------------------------------------------------------
/src/components/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as DialogPrimitive from "@radix-ui/react-dialog"
5 | import { Cross2Icon } from "@radix-ui/react-icons"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Dialog = DialogPrimitive.Root
10 |
11 | const DialogTrigger = DialogPrimitive.Trigger
12 |
13 | const DialogPortal = DialogPrimitive.Portal
14 |
15 | const DialogClose = DialogPrimitive.Close
16 |
17 | const DialogOverlay = React.forwardRef<
18 | React.ElementRef,
19 | React.ComponentPropsWithoutRef
20 | >(({ className, ...props }, ref) => (
21 |
29 | ))
30 | DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
31 |
32 | const DialogContent = React.forwardRef<
33 | React.ElementRef,
34 | React.ComponentPropsWithoutRef
35 | >(({ className, children, ...props }, ref) => (
36 |
37 |
38 |
46 | {children}
47 |
48 |
49 | Close
50 |
51 |
52 |
53 | ))
54 | DialogContent.displayName = DialogPrimitive.Content.displayName
55 |
56 | const DialogHeader = ({
57 | className,
58 | ...props
59 | }: React.HTMLAttributes) => (
60 |
67 | )
68 | DialogHeader.displayName = "DialogHeader"
69 |
70 | const DialogFooter = ({
71 | className,
72 | ...props
73 | }: React.HTMLAttributes) => (
74 |
81 | )
82 | DialogFooter.displayName = "DialogFooter"
83 |
84 | const DialogTitle = React.forwardRef<
85 | React.ElementRef,
86 | React.ComponentPropsWithoutRef
87 | >(({ className, ...props }, ref) => (
88 |
96 | ))
97 | DialogTitle.displayName = DialogPrimitive.Title.displayName
98 |
99 | const DialogDescription = React.forwardRef<
100 | React.ElementRef,
101 | React.ComponentPropsWithoutRef
102 | >(({ className, ...props }, ref) => (
103 |
108 | ))
109 | DialogDescription.displayName = DialogPrimitive.Description.displayName
110 |
111 | export {
112 | Dialog,
113 | DialogPortal,
114 | DialogOverlay,
115 | DialogTrigger,
116 | DialogClose,
117 | DialogContent,
118 | DialogHeader,
119 | DialogFooter,
120 | DialogTitle,
121 | DialogDescription,
122 | }
123 |
--------------------------------------------------------------------------------
/src/components/ui/input.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | export interface InputProps
6 | extends React.InputHTMLAttributes { customProp?: string; // Add any custom props here in the future.
7 | }
8 |
9 | const Input = React.forwardRef(
10 | ({ className, type, ...props }, ref) => {
11 | return (
12 |
21 | )
22 | }
23 | )
24 | Input.displayName = "Input"
25 |
26 | export { Input }
27 |
--------------------------------------------------------------------------------
/src/components/ui/kanban.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { Card } from '@/components/ui/card';
4 | import { cn } from '@/lib/utils';
5 | import {
6 | DndContext,
7 | rectIntersection,
8 | useDraggable,
9 | useDroppable,
10 | TouchSensor,
11 | MouseSensor,
12 | useSensor,
13 | useSensors,
14 | } from '@dnd-kit/core';
15 | import type { DragEndEvent } from '@dnd-kit/core';
16 | import type { ReactNode } from 'react';
17 |
18 | export type Status = {
19 | id: string;
20 | name: string;
21 | color: string;
22 | };
23 |
24 | export type Feature = {
25 | id: string;
26 | name: string;
27 | startAt: Date;
28 | endAt: Date;
29 | status: Status;
30 | };
31 |
32 | export type KanbanBoardProps = {
33 | id: Status['id'];
34 | children: ReactNode;
35 | className?: string;
36 | };
37 |
38 | export const KanbanBoard = ({ id, children, className }: KanbanBoardProps) => {
39 | const { isOver, setNodeRef } = useDroppable({ id });
40 |
41 | return (
42 |
50 | {children}
51 |
52 | );
53 | };
54 |
55 | export type KanbanCardProps = Pick & {
56 | index: number;
57 | parent: string;
58 | children?: ReactNode;
59 | className?: string;
60 | };
61 |
62 | export const KanbanCard = ({
63 | id,
64 | name,
65 | index,
66 | parent,
67 | children,
68 | className,
69 | }: KanbanCardProps) => {
70 | const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({
71 | id,
72 | data: { index, parent },
73 | });
74 |
75 | return (
76 |
89 |
96 |
97 |
98 | {children ??
{name}
}
99 |
100 |
101 | );
102 | };
103 |
104 | export type KanbanCardsProps = {
105 | children: ReactNode;
106 | className?: string;
107 | };
108 |
109 | export const KanbanCards = ({ children, className }: KanbanCardsProps) => (
110 | {children}
111 | );
112 |
113 | export type KanbanHeaderProps =
114 | | {
115 | children: ReactNode;
116 | }
117 | | {
118 | name: Status['name'];
119 | color: Status['color'];
120 | className?: string;
121 | };
122 |
123 | export const KanbanHeader = (props: KanbanHeaderProps) =>
124 | 'children' in props ? (
125 | props.children
126 | ) : (
127 |
128 |
132 |
{props.name}
133 |
134 | );
135 |
136 | export type KanbanProviderProps = {
137 | children: ReactNode;
138 | onDragEnd: (event: DragEndEvent) => void;
139 | className?: string;
140 | };
141 |
142 | export const KanbanProvider = ({
143 | children,
144 | onDragEnd,
145 | className,
146 | }: KanbanProviderProps) => {
147 | const mouseSensor = useSensor(MouseSensor, {
148 | activationConstraint: {
149 | distance: 10, // 10px movement required before drag starts
150 | },
151 | });
152 |
153 | const touchSensor = useSensor(TouchSensor, {
154 | activationConstraint: {
155 | delay: 250, // Wait 250ms before activating
156 | tolerance: 5, // Allow 5px movement during delay
157 | },
158 | });
159 |
160 | const sensors = useSensors(mouseSensor, touchSensor);
161 |
162 | return (
163 |
168 |
174 | {children}
175 |
176 |
177 | );
178 | };
--------------------------------------------------------------------------------
/src/components/ui/label.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as LabelPrimitive from "@radix-ui/react-label"
5 | import { cva, type VariantProps } from "class-variance-authority"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const labelVariants = cva(
10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11 | )
12 |
13 | const Label = React.forwardRef<
14 | React.ElementRef,
15 | React.ComponentPropsWithoutRef &
16 | VariantProps
17 | >(({ className, ...props }, ref) => (
18 |
23 | ))
24 | Label.displayName = LabelPrimitive.Root.displayName
25 |
26 | export { Label }
27 |
--------------------------------------------------------------------------------
/src/components/ui/popover.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as PopoverPrimitive from "@radix-ui/react-popover"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Popover = PopoverPrimitive.Root
9 |
10 | const PopoverTrigger = PopoverPrimitive.Trigger
11 |
12 | const PopoverAnchor = PopoverPrimitive.Anchor
13 |
14 | const PopoverContent = React.forwardRef<
15 | React.ElementRef,
16 | React.ComponentPropsWithoutRef
17 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
18 |
19 |
29 |
30 | ))
31 | PopoverContent.displayName = PopoverPrimitive.Content.displayName
32 |
33 | export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
34 |
--------------------------------------------------------------------------------
/src/components/ui/scroll-area.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const ScrollArea = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, children, ...props }, ref) => (
12 |
17 |
18 | {children}
19 |
20 |
21 |
22 |
23 | ))
24 | ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
25 |
26 | const ScrollBar = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, orientation = "vertical", ...props }, ref) => (
30 |
43 |
44 |
45 | ))
46 | ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
47 |
48 | export { ScrollArea, ScrollBar }
49 |
--------------------------------------------------------------------------------
/src/components/ui/switch.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SwitchPrimitives from "@radix-ui/react-switch"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Switch = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 |
25 |
26 | ))
27 | Switch.displayName = SwitchPrimitives.Root.displayName
28 |
29 | export { Switch }
30 |
--------------------------------------------------------------------------------
/src/components/ui/textarea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | const Textarea = React.forwardRef<
6 | HTMLTextAreaElement,
7 | React.ComponentProps<"textarea">
8 | >(({ className, ...props }, ref) => {
9 | return (
10 |
18 | )
19 | })
20 | Textarea.displayName = "Textarea"
21 |
22 | export { Textarea }
23 |
--------------------------------------------------------------------------------
/src/components/ui/toaster.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { useToast } from "@/hooks/use-toast"
4 | import {
5 | Toast,
6 | ToastClose,
7 | ToastDescription,
8 | ToastProvider,
9 | ToastTitle,
10 | ToastViewport,
11 | } from "@/components/ui/toast"
12 |
13 | export function Toaster() {
14 | const { toasts } = useToast()
15 |
16 | return (
17 |
18 | {toasts.map(function ({ id, title, description, action, ...props }) {
19 | return (
20 |
21 |
22 | {title && {title}}
23 | {description && (
24 | {description}
25 | )}
26 |
27 | {action}
28 |
29 |
30 | )
31 | })}
32 |
33 |
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/src/helpers/SendEmail.js:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { revalidatePath } from "next/cache";
3 | import nodemailer from "nodemailer";
4 |
5 | export async function sendMail({ to, name, subject, body }) {
6 | revalidatePath("/sign-up");
7 | const { SMTP_EMAIL, SMTP_PASSWORD } = process.env;
8 |
9 | if (!SMTP_EMAIL || !SMTP_PASSWORD) {
10 | console.error("SMTP credentials are missing");
11 | return;
12 | }
13 |
14 | const transport = nodemailer.createTransport({
15 | service: "gmail",
16 | auth: {
17 | user: SMTP_EMAIL,
18 | pass: SMTP_PASSWORD,
19 | },
20 | });
21 |
22 |
23 | try {
24 | await transport.verify();
25 | // console.log("SMTP connection successful");
26 | } catch (error) {
27 | // console.error("SMTP connection error:", error);
28 | return;
29 | }
30 |
31 |
32 | const emailHtml = `
33 |
34 |
Hello, ${name}
35 |
36 | Thank you for registering on SNIPPETS. Please use the following verification code to complete your registration:
37 |
38 |
39 |
${body}
40 |
41 |
42 | If you did not request this code, please ignore this email.
43 |
44 |
45 | Regards,
The SNIPPETS Team
46 |
47 |
48 | `;
49 |
50 |
51 |
52 | try {
53 | const sendResult = await transport.sendMail({
54 | from: SMTP_EMAIL,
55 | to,
56 | subject,
57 | html: emailHtml,
58 | });
59 | // console.log("Email sent successfully:", sendResult);
60 | } catch (error) {
61 | console.error("Error sending email:", error);
62 | }
63 | }
--------------------------------------------------------------------------------
/src/helpers/SendIt.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 | import { sendMail } from "@/helpers/SendEmail";
3 |
4 | interface SenditProps {
5 | to: string,
6 | name: string,
7 | subject: string,
8 | body: string
9 | }
10 | const Sendit =async ({to, name, subject, body}: SenditProps) => {
11 | await sendMail({to, name, subject, body})
12 | return;
13 | }
14 |
15 | export default Sendit
--------------------------------------------------------------------------------
/src/helpers/VerificationEmail.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | Html,
3 | Head,
4 | Font,
5 | Preview,
6 | Heading,
7 | Row,
8 | Section,
9 | Text,
10 | Button,
11 | } from '@react-email/components';
12 |
13 |
14 | export default function VerificationEmail({ username, otp }) {
15 | return (
16 |
17 |
18 | Verification Code
19 |
29 |
30 | Here's your verification code: {otp}
31 |
32 |
33 | Hello {username},
34 |
35 |
36 |
37 | Thank you for registering on JOBSPHERE. Please use the following verification
38 | code to complete your registration:
39 |
40 |
41 |
42 | {otp}
43 |
44 |
45 |
46 | If you did not request this code, please ignore this email.
47 |
48 |
49 | {/*
50 |
56 |
*/}
57 |
58 |
59 | );
60 | }
--------------------------------------------------------------------------------
/src/hooks/use-toast.ts:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | // Inspired by react-hot-toast library
4 | import * as React from "react"
5 |
6 | import type {
7 | ToastActionElement,
8 | ToastProps,
9 | } from "@/components/ui/toast"
10 |
11 | const TOAST_LIMIT = 1
12 | const TOAST_REMOVE_DELAY = 1000000
13 |
14 | type ToasterToast = ToastProps & {
15 | id: string
16 | title?: React.ReactNode
17 | description?: React.ReactNode
18 | action?: ToastActionElement
19 | }
20 |
21 | const actionTypes = {
22 | ADD_TOAST: "ADD_TOAST",
23 | UPDATE_TOAST: "UPDATE_TOAST",
24 | DISMISS_TOAST: "DISMISS_TOAST",
25 | REMOVE_TOAST: "REMOVE_TOAST",
26 | } as const
27 |
28 | let count = 0
29 |
30 | function genId() {
31 | count = (count + 1) % Number.MAX_SAFE_INTEGER
32 | return count.toString()
33 | }
34 |
35 | type ActionType = typeof actionTypes
36 |
37 | type Action =
38 | | {
39 | type: ActionType["ADD_TOAST"]
40 | toast: ToasterToast
41 | }
42 | | {
43 | type: ActionType["UPDATE_TOAST"]
44 | toast: Partial
45 | }
46 | | {
47 | type: ActionType["DISMISS_TOAST"]
48 | toastId?: ToasterToast["id"]
49 | }
50 | | {
51 | type: ActionType["REMOVE_TOAST"]
52 | toastId?: ToasterToast["id"]
53 | }
54 |
55 | interface State {
56 | toasts: ToasterToast[]
57 | }
58 |
59 | const toastTimeouts = new Map>()
60 |
61 | const addToRemoveQueue = (toastId: string) => {
62 | if (toastTimeouts.has(toastId)) {
63 | return
64 | }
65 |
66 | const timeout = setTimeout(() => {
67 | toastTimeouts.delete(toastId)
68 | dispatch({
69 | type: "REMOVE_TOAST",
70 | toastId: toastId,
71 | })
72 | }, TOAST_REMOVE_DELAY)
73 |
74 | toastTimeouts.set(toastId, timeout)
75 | }
76 |
77 | export const reducer = (state: State, action: Action): State => {
78 | switch (action.type) {
79 | case "ADD_TOAST":
80 | return {
81 | ...state,
82 | toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
83 | }
84 |
85 | case "UPDATE_TOAST":
86 | return {
87 | ...state,
88 | toasts: state.toasts.map((t) =>
89 | t.id === action.toast.id ? { ...t, ...action.toast } : t
90 | ),
91 | }
92 |
93 | case "DISMISS_TOAST": {
94 | const { toastId } = action
95 |
96 | // ! Side effects ! - This could be extracted into a dismissToast() action,
97 | // but I'll keep it here for simplicity
98 | if (toastId) {
99 | addToRemoveQueue(toastId)
100 | } else {
101 | state.toasts.forEach((toast) => {
102 | addToRemoveQueue(toast.id)
103 | })
104 | }
105 |
106 | return {
107 | ...state,
108 | toasts: state.toasts.map((t) =>
109 | t.id === toastId || toastId === undefined
110 | ? {
111 | ...t,
112 | open: false,
113 | }
114 | : t
115 | ),
116 | }
117 | }
118 | case "REMOVE_TOAST":
119 | if (action.toastId === undefined) {
120 | return {
121 | ...state,
122 | toasts: [],
123 | }
124 | }
125 | return {
126 | ...state,
127 | toasts: state.toasts.filter((t) => t.id !== action.toastId),
128 | }
129 | }
130 | }
131 |
132 | const listeners: Array<(state: State) => void> = []
133 |
134 | let memoryState: State = { toasts: [] }
135 |
136 | function dispatch(action: Action) {
137 | memoryState = reducer(memoryState, action)
138 | listeners.forEach((listener) => {
139 | listener(memoryState)
140 | })
141 | }
142 |
143 | type Toast = Omit
144 |
145 | function toast({ ...props }: Toast) {
146 | const id = genId()
147 |
148 | const update = (props: ToasterToast) =>
149 | dispatch({
150 | type: "UPDATE_TOAST",
151 | toast: { ...props, id },
152 | })
153 | const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
154 |
155 | dispatch({
156 | type: "ADD_TOAST",
157 | toast: {
158 | ...props,
159 | id,
160 | open: true,
161 | onOpenChange: (open) => {
162 | if (!open) dismiss()
163 | },
164 | },
165 | })
166 |
167 | return {
168 | id: id,
169 | dismiss,
170 | update,
171 | }
172 | }
173 |
174 | function useToast() {
175 | const [state, setState] = React.useState(memoryState)
176 |
177 | React.useEffect(() => {
178 | listeners.push(setState)
179 | return () => {
180 | const index = listeners.indexOf(setState)
181 | if (index > -1) {
182 | listeners.splice(index, 1)
183 | }
184 | }
185 | }, [state])
186 |
187 | return {
188 | ...state,
189 | toast,
190 | dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
191 | }
192 | }
193 |
194 | export { useToast, toast }
195 |
--------------------------------------------------------------------------------
/src/lib/LanguageData.ts:
--------------------------------------------------------------------------------
1 | export const programmingLanguages = [
2 | 'Assembly',
3 | 'Bash',
4 | 'C',
5 | 'C#',
6 | 'C++',
7 | 'Clojure',
8 | 'COBOL',
9 | 'Crystal',
10 | 'D',
11 | 'Dart',
12 | 'Elixir',
13 | 'Elm',
14 | 'Erlang',
15 | 'F#',
16 | 'Go',
17 | 'Groovy',
18 | 'Haskell',
19 | 'HTML',
20 | 'Java',
21 | 'JavaScript',
22 | 'Kotlin',
23 | 'Lisp',
24 | 'Lua',
25 | 'MATLAB',
26 | 'Objective-C',
27 | 'Pascal',
28 | 'Perl',
29 | 'PHP',
30 | 'Prolog',
31 | 'Python',
32 | 'R',
33 | 'Ruby',
34 | 'Rust',
35 | 'Scala',
36 | 'Shell',
37 | 'SQL',
38 | 'Swift',
39 | 'TypeScript',
40 | 'VBScript',
41 | 'Visual Basic',
42 | 'WebAssembly'
43 | ];
44 |
--------------------------------------------------------------------------------
/src/lib/cloudinary.ts:
--------------------------------------------------------------------------------
1 | import {v2 as cloudinary} from 'cloudinary';
2 |
3 | cloudinary.config({
4 | cloud_name: process.env.CLOUD_NAME,
5 | api_key: process.env.CLOUDINARY_API_KEY,
6 | api_secret: process.env.CLOUDINARY_API_SECRET
7 | });
8 |
9 | export { cloudinary };
--------------------------------------------------------------------------------
/src/lib/cloudinaryImageUploader.ts:
--------------------------------------------------------------------------------
1 | import { cloudinary } from "./cloudinary";
2 |
3 | export interface CloudinaryUploadResult {
4 | secure_url: string;
5 | public_id?: string;
6 | version?: number;
7 | signature?: string;
8 | width?: number;
9 | height?: number;
10 | format?: string;
11 | resource_type?: string;
12 | created_at?: string;
13 | tags?: string[];
14 | bytes?: number;
15 | type?: string;
16 | etag?: string;
17 | placeholder?: boolean;
18 | url?: string;
19 | access_mode?: string;
20 | original_filename?: string;
21 | }
22 |
23 |
24 | export const uploadImageCloudinary = async (file: File, folder: string) => {
25 |
26 | const buffer = await file.arrayBuffer();
27 | const byte = Buffer.from(buffer);
28 |
29 | return new Promise(async (resolve, reject) => {
30 | const stream = await cloudinary.uploader.upload_stream(
31 | {
32 | resource_type: 'auto',
33 | folder: folder,
34 | },
35 | async (error: any, result: any) => {
36 | if (error) {
37 | return reject(error);
38 | }
39 | resolve(result as CloudinaryUploadResult);
40 | }
41 | ).end(byte);
42 |
43 |
44 | });
45 | };
--------------------------------------------------------------------------------
/src/lib/constants.ts:
--------------------------------------------------------------------------------
1 | export const LANGUAGE_VERSIONS = {
2 | javascript: "18.15.0",
3 | typescript: "5.0.3",
4 | python: "3.10.0",
5 | java: "15.0.2",
6 | csharp: "6.12.0",
7 | php: "8.2.3",
8 | c: "10.2.0",
9 | cpp: "10.2.0"
10 | };
11 |
12 | export const CODE_SNIPPETS = {
13 | javascript: `\nfunction greet(name) {\n\tconsole.log("Hello, " + name + "!");\n}\n\ngreet("Alex");\n`,
14 | typescript: `\ntype Params = {\n\tname: string;\n}\n\nfunction greet(data: Params) {\n\tconsole.log("Hello, " + data.name + "!");\n}\n\ngreet({ name: "Alex" });\n`,
15 | python: `\ndef greet(name):\n\tprint("Hello, " + name + "!")\n\ngreet("Alex")\n`,
16 | java: `\npublic class HelloWorld {\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println("Hello World");\n\t}\n}\n`,
17 | csharp: 'using System;\n\nnamespace HelloWorld\n{\n\tclass Hello { \n\t\tstatic void Main(string[] args) {\n\t\t\tConsole.WriteLine("Hello World in C#");\n\t\t}\n\t}\n}\n',
18 | php: "\n\nint main() {\n\tchar name[] = "Alex";\n\tprintf("Hello, %s!\\n", name);\n\treturn 0;\n}\n`,
20 | cpp: `#include \n#include \n\nint main() {\n\tstd::string name = "Alex";\n\tstd::cout << "Hello, " << name << "!" << std::endl;\n\treturn 0;\n}\n`
21 | };
--------------------------------------------------------------------------------
/src/lib/pusher/client/index.ts:
--------------------------------------------------------------------------------
1 | import PusherClient from "pusher-js";
2 |
3 | export const pusherClient = new PusherClient(process.env.NEXT_PUBLIC_PUSHER_KEY as string, {
4 | cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER as string,
5 | authEndpoint: "/api/pusher/auth",
6 | });
--------------------------------------------------------------------------------
/src/lib/pusher/server/index.ts:
--------------------------------------------------------------------------------
1 | import PusherServer from 'pusher';
2 |
3 | let pusherInstance: PusherServer | null = null;
4 |
5 | export const getPusherInstance = () => {
6 | if (!pusherInstance) {
7 | pusherInstance = new PusherServer({
8 | appId: process.env.PUSHER_APP_ID as string,
9 | key: process.env.NEXT_PUBLIC_PUSHER_KEY as string,
10 | secret: process.env.PUSHER_SECRET as string,
11 | cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER as string,
12 | useTLS: true,
13 | });
14 | }
15 | return pusherInstance;
16 | };
--------------------------------------------------------------------------------
/src/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { clsx, type ClassValue } from "clsx"
2 | import { twMerge } from "tailwind-merge"
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs))
6 | }
7 |
--------------------------------------------------------------------------------
/src/middleware.ts:
--------------------------------------------------------------------------------
1 | import { NextResponse } from 'next/server'
2 | import type { NextRequest } from 'next/server'
3 | import { cookies } from 'next/headers';
4 |
5 | export const config = {
6 | matcher: ["/", '/profile', '/uploadSnippets', '/description/:path*', '/userChat', '/login', '/sign-up'],
7 | }
8 |
9 | // '/profile/:path*'
10 | export async function middleware(request: NextRequest) {
11 | const cookie = cookies();
12 | const getUserCookie = cookie.get("snippets")?.value;
13 | const url = request.nextUrl;
14 | // console.log(url)
15 | if (getUserCookie && (url.pathname.startsWith("/login") || url.pathname.startsWith("/sign-up"))) {
16 | return NextResponse.redirect(new URL('/', request.url));
17 | }
18 |
19 | if (!getUserCookie && url.pathname.startsWith("/profile")) {
20 | return NextResponse.redirect(new URL('/login', request.url));
21 | }
22 |
23 | if (!getUserCookie && url.pathname.startsWith("/uploadSnippets")) {
24 | return NextResponse.redirect(new URL('/login', request.url));
25 | }
26 |
27 | if (!getUserCookie && url.pathname.startsWith("/description")) {
28 | return NextResponse.redirect(new URL('/login', request.url));
29 | }
30 |
31 | if (!getUserCookie && url.pathname.startsWith("/userChat")) {
32 | return NextResponse.redirect(new URL('/login', request.url));
33 | }
34 | return NextResponse.next();
35 | }
36 |
--------------------------------------------------------------------------------
/src/types/ChangePasswordTypes.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { zodResolver } from "@hookform/resolvers/zod";
3 |
4 |
5 |
6 |
7 | const SchemaForChangePassword = z.object({
8 | password: z.string().min(6, { message: "Password must have atleast 6 characters" }),
9 | confirmPassword: z.string().min(6, { message: "Password must have atleast 6 characters" })
10 | })
11 |
12 |
13 | export type changePasswordTypes = z.infer;
14 | export const changePasswordResolver = zodResolver(SchemaForChangePassword);
--------------------------------------------------------------------------------
/src/types/LoginTypes.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { zodResolver } from "@hookform/resolvers/zod";
3 |
4 |
5 | const UsernameValidation = z.string().min(3, {
6 | message: "Username is too small"
7 | })
8 |
9 |
10 | const SchemaForLogin = z.object({
11 | username: UsernameValidation,
12 | password: z.string().min(6, { message: "Password must have atleast 6 characters" })
13 | })
14 |
15 |
16 | export type loginTypes = z.infer;
17 | export const loginResolver = zodResolver(SchemaForLogin);
--------------------------------------------------------------------------------
/src/types/SignupTypes.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { zodResolver } from "@hookform/resolvers/zod";
3 |
4 |
5 | const UsernameValidation = z.string().min(3, {
6 | message: "Username is too small"
7 | }).max(20, "Username must have atmost 20 characters")
8 | .regex(/^[a-zA-Z0-9_]*$/, "Username must contain only letters, numbers and underscores")
9 |
10 |
11 | const SchemaForSignup = z.object({
12 | username: UsernameValidation,
13 | name: z.string().min(3, { message: "Name is too shorter" }).max(20, { message: "Name is too longer" }),
14 | email: z.string().email({ message: "Invalid email address" }),
15 | password: z.string().min(6, { message: "Password must have atleast 6 characters" })
16 | })
17 |
18 |
19 | export type signUpTypes = z.infer;
20 | export const SignupResolver = zodResolver(SchemaForSignup);
--------------------------------------------------------------------------------
/src/types/forgotPasswordTypes.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { zodResolver } from "@hookform/resolvers/zod";
3 |
4 |
5 |
6 |
7 | const SchemaForVerifyEmailForgotPassword = z.object({
8 | email: z.string().email({ message: "Invalid email address" }),
9 | otp: z.string()
10 | })
11 |
12 |
13 | export type VerifyEmailforgotPasswordTypes = z.infer;
14 | export const VerifyEmailforgotPasswordResolver = zodResolver(SchemaForVerifyEmailForgotPassword );
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const config: Config = {
4 | darkMode: ["class"],
5 | content: [
6 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
8 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
9 | ],
10 | theme: {
11 | extend: {
12 | colors: {
13 | background: 'hsl(var(--background))',
14 | foreground: 'hsl(var(--foreground))',
15 | card: {
16 | DEFAULT: 'hsl(var(--card))',
17 | foreground: 'hsl(var(--card-foreground))'
18 | },
19 | popover: {
20 | DEFAULT: 'hsl(var(--popover))',
21 | foreground: 'hsl(var(--popover-foreground))'
22 | },
23 | primary: {
24 | DEFAULT: 'hsl(var(--primary))',
25 | foreground: 'hsl(var(--primary-foreground))'
26 | },
27 | secondary: {
28 | DEFAULT: 'hsl(var(--secondary))',
29 | foreground: 'hsl(var(--secondary-foreground))'
30 | },
31 | muted: {
32 | DEFAULT: 'hsl(var(--muted))',
33 | foreground: 'hsl(var(--muted-foreground))'
34 | },
35 | accent: {
36 | DEFAULT: 'hsl(var(--accent))',
37 | foreground: 'hsl(var(--accent-foreground))'
38 | },
39 | destructive: {
40 | DEFAULT: 'hsl(var(--destructive))',
41 | foreground: 'hsl(var(--destructive-foreground))'
42 | },
43 | border: 'hsl(var(--border))',
44 | input: 'hsl(var(--input))',
45 | ring: 'hsl(var(--ring))',
46 | chart: {
47 | '1': 'hsl(var(--chart-1))',
48 | '2': 'hsl(var(--chart-2))',
49 | '3': 'hsl(var(--chart-3))',
50 | '4': 'hsl(var(--chart-4))',
51 | '5': 'hsl(var(--chart-5))'
52 | }
53 | },
54 | borderRadius: {
55 | lg: 'var(--radius)',
56 | md: 'calc(var(--radius) - 2px)',
57 | sm: 'calc(var(--radius) - 4px)'
58 | }
59 | }
60 | },
61 | plugins: [require("tailwindcss-animate")],
62 | };
63 | export default config;
64 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": true,
7 | "noEmit": true,
8 | "esModuleInterop": true,
9 | "module": "esnext",
10 | "moduleResolution": "bundler",
11 | "resolveJsonModule": true,
12 | "isolatedModules": true,
13 | "jsx": "preserve",
14 | "incremental": true,
15 | "plugins": [
16 | {
17 | "name": "next"
18 | }
19 | ],
20 | "paths": {
21 | "@/*": ["./src/*"]
22 | }
23 | },
24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/helpers/SendEmail.js"],
25 | "exclude": ["node_modules"]
26 | }
27 |
--------------------------------------------------------------------------------