├── .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 | [![snippet-1.png](https://i.postimg.cc/c1hMgQ7P/snippet-1.png)](https://postimg.cc/MXcjgfFY) 16 | 17 | [![snippet-2.png](https://i.postimg.cc/V6VfpZQ3/snippet-2.png)](https://postimg.cc/8JLgrHCH) 18 | 19 | [![snippet-3.png](https://i.postimg.cc/ZKkBqn2X/snippet-3.png)](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 |
74 |
75 |
76 | 82 |
83 | 90 | {errors.password?.message && ( 91 |
{errors.password.message}
92 | )} 93 |
94 | 95 | {/* Password Field */} 96 |
97 | 103 | 110 | {errors.confirmPassword?.message && ( 111 |
112 | {errors.confirmPassword.message} 113 |
114 | )} 115 |
116 | 117 | {/* Submit Button */} 118 | 124 | {loading && } 125 | Change Password 126 | 127 |
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 |
78 | {/* OTP Field */} 79 |
80 | 86 | setOtp(e.target.value)} 91 | className="w-full px-4 py-3 rounded-xl dark:text-black outline-none bg-gray-100 transition" 92 | placeholder="8767" 93 | /> 94 | 95 | {/* Display validation error */} 96 | {errors.otp?.message && ( 97 |
{errors.otp.message}
98 | )} 99 |
100 | 101 | {/* Submit Button */} 102 | 108 |
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 |
37 |
38 |
39 |
40 |
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 | hero 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 |