├── README.md
├── .eslintrc.json
├── app
├── api
│ ├── auth
│ │ └── [...nextauth]
│ │ │ └── route.ts
│ └── user
│ │ ├── getfeed
│ │ └── route.ts
│ │ ├── createpost
│ │ └── route.ts
│ │ ├── likepost
│ │ └── route.ts
│ │ ├── unlikepost
│ │ └── route.ts
│ │ └── addresourse
│ │ └── route.ts
├── favicon.ico
├── opengraph-image.png
├── dashboard
│ ├── explore
│ │ └── page.tsx
│ ├── bookmarks
│ │ └── page.tsx
│ ├── _page.tsx
│ ├── feed
│ │ ├── getfeed.ts
│ │ ├── page.tsx
│ │ └── posts.tsx
│ ├── profile
│ │ ├── userposts.ts
│ │ └── page.tsx
│ └── layout.tsx
├── providers.tsx
├── resources
│ ├── _page.tsx
│ ├── all
│ │ ├── getall.ts
│ │ └── page.tsx
│ ├── aiml
│ │ ├── getAIML.ts
│ │ └── page.tsx
│ ├── devops
│ │ ├── getDevOps.ts
│ │ └── page.tsx
│ ├── webdev
│ │ ├── getWebDev.ts
│ │ └── page.tsx
│ ├── blockchain
│ │ ├── getBlockchain.ts
│ │ └── page.tsx
│ ├── layout.tsx
│ ├── resourcecard.tsx
│ ├── add
│ │ └── page.tsx
│ └── sidepanel.tsx
├── community
│ └── page.tsx
├── reviews
│ └── page.tsx
├── opportunities
│ └── page.tsx
├── register
│ └── page.tsx
├── signIn
│ └── page.tsx
├── domains
│ └── page.tsx
├── layout.tsx
├── page.tsx
└── globals.css
├── public
├── bg1.png
├── bg2.png
├── bg3.png
├── mit.png
├── nasa.png
├── penn.png
├── oxford.png
├── cambridge.png
├── stanford.png
├── unsightcover.png
├── vercel.svg
└── next.svg
├── next.config.mjs
├── prisma
├── migrations
│ ├── 20240421202652_init
│ │ └── migration.sql
│ ├── 20240425162102_init
│ │ └── migration.sql
│ ├── 20240426192955_init
│ │ └── migration.sql
│ ├── 20240428205535_added
│ │ └── migration.sql
│ ├── migration_lock.toml
│ ├── 20240425164420_init
│ │ └── migration.sql
│ ├── 20240428210139_removed
│ │ └── migration.sql
│ ├── 20240421200914_init
│ │ └── migration.sql
│ ├── 20240428205649_added
│ │ └── migration.sql
│ ├── 20240424200156_init
│ │ └── migration.sql
│ ├── 20240427221532_added
│ │ └── migration.sql
│ ├── 20240427225515_modefied
│ │ └── migration.sql
│ ├── 20240424202227_init
│ │ └── migration.sql
│ ├── 20240424183057_init
│ │ └── migration.sql
│ ├── 20240424202049_init
│ │ └── migration.sql
│ └── 20240421200423_init
│ │ └── migration.sql
└── schema.prisma
├── postcss.config.mjs
├── .env.example
├── components
├── user
│ ├── resources.tsx
│ ├── reviews.tsx
│ ├── opportunity.tsx
│ ├── community.tsx
│ ├── throttle.ts
│ ├── profile.tsx
│ └── postPanel.tsx
├── Update.tsx
├── auth
│ ├── signoutBtn.tsx
│ ├── sideSection.tsx
│ ├── signinWithEmail.tsx
│ └── registerWithCred.tsx
├── ui
│ ├── label.tsx
│ ├── input.tsx
│ ├── toaster.tsx
│ ├── sonner.tsx
│ ├── button.tsx
│ ├── card.tsx
│ ├── use-toast.ts
│ ├── form.tsx
│ └── toast.tsx
├── mainpage
│ ├── featureCard.tsx
│ ├── mainpagetitle.tsx
│ ├── imagebanner.tsx
│ ├── intro.tsx
│ ├── mainpage.tsx
│ └── footer.tsx
├── underdevelopment.tsx
├── reveal.tsx
├── postCard.tsx
├── explorebar.tsx
├── landing.tsx
├── navbar.tsx
└── sidebar.tsx
├── lib
├── utils.ts
├── db.ts
├── resend.ts
└── token.ts
├── components.json
├── schema
└── index.ts
├── .gitignore
├── utils
├── verification-token.ts
└── user.ts
├── auth.config.ts
├── tsconfig.json
├── auth.ts
├── actions
├── register.ts
└── login.ts
├── package.json
├── config
└── site-config.ts
└── tailwind.config.ts
/README.md:
--------------------------------------------------------------------------------
1 | ## under development
2 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/app/api/auth/[...nextauth]/route.ts:
--------------------------------------------------------------------------------
1 | export { GET, POST } from "@/auth";
2 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/app/favicon.ico
--------------------------------------------------------------------------------
/public/bg1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/bg1.png
--------------------------------------------------------------------------------
/public/bg2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/bg2.png
--------------------------------------------------------------------------------
/public/bg3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/bg3.png
--------------------------------------------------------------------------------
/public/mit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/mit.png
--------------------------------------------------------------------------------
/public/nasa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/nasa.png
--------------------------------------------------------------------------------
/public/penn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/penn.png
--------------------------------------------------------------------------------
/public/oxford.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/oxford.png
--------------------------------------------------------------------------------
/public/cambridge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/cambridge.png
--------------------------------------------------------------------------------
/public/stanford.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/stanford.png
--------------------------------------------------------------------------------
/app/opengraph-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/app/opengraph-image.png
--------------------------------------------------------------------------------
/public/unsightcover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kartikver15gr8/Unsight/HEAD/public/unsightcover.png
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {};
3 |
4 | export default nextConfig;
5 |
--------------------------------------------------------------------------------
/prisma/migrations/20240421202652_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- AlterTable
2 | ALTER TABLE "User" ADD COLUMN "password" TEXT;
3 |
--------------------------------------------------------------------------------
/prisma/migrations/20240425162102_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- AlterTable
2 | ALTER TABLE "Posts" ADD COLUMN "userImg" TEXT;
3 |
--------------------------------------------------------------------------------
/prisma/migrations/20240426192955_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- AlterTable
2 | ALTER TABLE "Posts" ALTER COLUMN "like" SET DEFAULT 0;
3 |
--------------------------------------------------------------------------------
/prisma/migrations/20240428205535_added/migration.sql:
--------------------------------------------------------------------------------
1 | -- AlterTable
2 | ALTER TABLE "Posts" ADD COLUMN "thumbnailUrl" TEXT;
3 |
--------------------------------------------------------------------------------
/app/dashboard/explore/page.tsx:
--------------------------------------------------------------------------------
1 | import Landing from "@/components/landing";
2 |
3 | export default function Explore() {
4 | return ;
5 | }
6 |
--------------------------------------------------------------------------------
/app/dashboard/bookmarks/page.tsx:
--------------------------------------------------------------------------------
1 | import Landing from "@/components/landing";
2 |
3 | export default function Bookmarks() {
4 | return ;
5 | }
6 |
--------------------------------------------------------------------------------
/prisma/migrations/migration_lock.toml:
--------------------------------------------------------------------------------
1 | # Please do not edit this file manually
2 | # It should be added in your version-control system (i.e. Git)
3 | provider = "postgresql"
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | DATABASE_URL=
2 | EMAIL_SERVER_HOST=
3 | EMAIL_SERVER_PORT=
4 | EMAIL_SERVER_USER=
5 | EMAIL_SERVER_PASSWORD=
6 | EMAIL_FROM=
7 | RESEND_API_KEY=
8 | AUTH_SECRET=
9 | AUTH_RESEND_KEY=
--------------------------------------------------------------------------------
/components/user/resources.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | export default function ResourcesPage() {
3 | return (
4 |
7 | );
8 | }
9 |
--------------------------------------------------------------------------------
/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { type ClassValue, clsx } from "clsx";
2 | import { twMerge } from "tailwind-merge";
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs));
6 | }
7 |
--------------------------------------------------------------------------------
/components/user/reviews.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | export default function ReviewPage() {
3 | return (
4 |
7 | );
8 | }
9 |
--------------------------------------------------------------------------------
/components/user/opportunity.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | export default function OpportunityPage() {
3 | return (
4 |
7 | );
8 | }
9 |
--------------------------------------------------------------------------------
/components/user/community.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | export default function CommunityPage() {
4 | return (
5 |
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/prisma/migrations/20240425164420_init/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `userImg` on the `Posts` table. All the data in the column will be lost.
5 |
6 | */
7 | -- AlterTable
8 | ALTER TABLE "Posts" DROP COLUMN "userImg";
9 |
--------------------------------------------------------------------------------
/app/providers.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 | import { SessionProvider } from "next-auth/react";
5 |
6 | export const Providers = ({ children }: { children: React.ReactNode }) => {
7 | return {children} ;
8 | };
9 |
--------------------------------------------------------------------------------
/app/resources/_page.tsx:
--------------------------------------------------------------------------------
1 | import Navbar from "@/components/navbar";
2 | import ResourcesPage from "@/components/user/resources";
3 | export default function Resources() {
4 | return (
5 |
6 |
7 |
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/prisma/migrations/20240428210139_removed/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `thumbnailUrl` on the `Resources` table. All the data in the column will be lost.
5 |
6 | */
7 | -- AlterTable
8 | ALTER TABLE "Resources" DROP COLUMN "thumbnailUrl";
9 |
--------------------------------------------------------------------------------
/lib/db.ts:
--------------------------------------------------------------------------------
1 | import { PrismaClient } from "@prisma/client";
2 |
3 | declare global {
4 | var prisma: PrismaClient | undefined;
5 | }
6 |
7 | export const prisma: PrismaClient = global.prisma || new PrismaClient();
8 |
9 | if (process.env.NODE_ENV === "development") global.prisma = prisma;
10 |
--------------------------------------------------------------------------------
/app/community/page.tsx:
--------------------------------------------------------------------------------
1 | import Navbar from "@/components/navbar";
2 | import CommunityPage from "@/components/user/community";
3 | export default function Community() {
4 | return (
5 |
6 |
7 |
8 |
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/prisma/migrations/20240421200914_init/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - A unique constraint covering the columns `[token]` on the table `VerificationToken` will be added. If there are existing duplicate values, this will fail.
5 |
6 | */
7 | -- CreateIndex
8 | CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token");
9 |
--------------------------------------------------------------------------------
/app/reviews/page.tsx:
--------------------------------------------------------------------------------
1 | import Navbar from "@/components/navbar";
2 | import UnderDevelopment from "@/components/underdevelopment";
3 | import ReviewPage from "@/components/user/reviews";
4 | export default function Resources() {
5 | return (
6 |
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/prisma/migrations/20240428205649_added/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `thumbnailUrl` on the `Posts` table. All the data in the column will be lost.
5 |
6 | */
7 | -- AlterTable
8 | ALTER TABLE "Posts" DROP COLUMN "thumbnailUrl";
9 |
10 | -- AlterTable
11 | ALTER TABLE "Resources" ADD COLUMN "thumbnailUrl" TEXT;
12 |
--------------------------------------------------------------------------------
/app/opportunities/page.tsx:
--------------------------------------------------------------------------------
1 | import Navbar from "@/components/navbar";
2 | import UnderDevelopment from "@/components/underdevelopment";
3 | import OpportunityPage from "@/components/user/opportunity";
4 | export default function Opportunites() {
5 | return (
6 |
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/app/register/page.tsx:
--------------------------------------------------------------------------------
1 | import RegisterCredentialsForm from "@/components/auth/registerWithCred";
2 | import { auth } from "@/auth";
3 | import { redirect } from "next/navigation";
4 | const RegisterPage = async () => {
5 | const session = await auth();
6 |
7 | return {session ? redirect("/") : }
;
8 | };
9 |
10 | export default RegisterPage;
11 |
--------------------------------------------------------------------------------
/app/signIn/page.tsx:
--------------------------------------------------------------------------------
1 | import SignInForm from "@/components/auth/signinWithEmail";
2 | import React from "react";
3 | import { redirect } from "next/navigation";
4 | import { auth } from "@/auth";
5 |
6 | const SignInPage = async () => {
7 | const session = await auth();
8 |
9 | return {session ? redirect("/") : }
;
10 | };
11 |
12 | export default SignInPage;
13 |
--------------------------------------------------------------------------------
/prisma/migrations/20240424200156_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- DropForeignKey
2 | ALTER TABLE "Posts" DROP CONSTRAINT "Posts_commentId_fkey";
3 |
4 | -- AlterTable
5 | ALTER TABLE "Posts" ALTER COLUMN "commentId" DROP NOT NULL;
6 |
7 | -- AddForeignKey
8 | ALTER TABLE "Posts" ADD CONSTRAINT "Posts_commentId_fkey" FOREIGN KEY ("commentId") REFERENCES "Comments"("id") ON DELETE SET NULL ON UPDATE CASCADE;
9 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "default",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "tailwind.config.ts",
8 | "css": "app/globals.css",
9 | "baseColor": "slate",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils"
16 | }
17 | }
--------------------------------------------------------------------------------
/components/Update.tsx:
--------------------------------------------------------------------------------
1 | export default function Update() {
2 | return (
3 |
4 |
5 | This Product is under development, Stay tuned for updates!
6 |
7 |
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/app/domains/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { universities } from "@/actions/domains";
3 | import { useEffect, useState } from "react";
4 |
5 | export default function Domains() {
6 | const [domains, setDomains] = useState();
7 | useEffect(() => {
8 | setDomains(universities);
9 | }, []);
10 | return (
11 |
12 |
{JSON.stringify(domains)}
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/components/auth/signoutBtn.tsx:
--------------------------------------------------------------------------------
1 | import { signOut } from "@/auth";
2 | import { Button } from "@/components/ui/button";
3 |
4 | const SignoutButton = () => {
5 | return (
6 |
7 |
15 |
16 | );
17 | };
18 |
19 | export default SignoutButton;
20 |
--------------------------------------------------------------------------------
/components/user/throttle.ts:
--------------------------------------------------------------------------------
1 | export const throttle = any>(
2 | func: T,
3 | delay: number
4 | ): ((...args: Parameters) => ReturnType | undefined) => {
5 | let lastCall = 0;
6 | return (...args: Parameters): ReturnType | undefined => {
7 | const now = new Date().getTime();
8 | if (now - lastCall < delay) {
9 | return;
10 | }
11 | lastCall = now;
12 | return func(...args);
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/app/resources/all/getall.ts:
--------------------------------------------------------------------------------
1 | import { prisma } from "@/lib/db";
2 | export const GetAllResources = async () => {
3 | const resources = await prisma.resources.findMany({});
4 | if (resources) {
5 | return resources;
6 | }
7 | return [
8 | {
9 | id: 1,
10 | title: "string",
11 | description: "string",
12 | userId: "string",
13 | categary: "string",
14 | upvotes: [""],
15 | resourceLink: "string",
16 | },
17 | ];
18 | };
19 |
--------------------------------------------------------------------------------
/schema/index.ts:
--------------------------------------------------------------------------------
1 | import * as z from "zod";
2 |
3 | export const LoginSchema = z.object({
4 | email: z.string().email({
5 | message: "Please enter a valid email address",
6 | }),
7 | });
8 |
9 | export const RegisterSchema = z.object({
10 | email: z.string().email({
11 | message: "Email is required",
12 | }),
13 | password: z.string().min(6, {
14 | message: "Minimum 6 characters required",
15 | }),
16 | name: z.string().min(2, {
17 | message: "Name is required",
18 | }),
19 | });
20 |
--------------------------------------------------------------------------------
/app/dashboard/_page.tsx:
--------------------------------------------------------------------------------
1 | import { auth, signOut } from "@/auth";
2 | import SignoutButton from "@/components/auth/signoutBtn";
3 | import { redirect } from "next/navigation";
4 | import Landing from "@/components/landing";
5 | import Sidebar from "@/components/sidebar";
6 | import Navbar from "@/components/navbar";
7 | import Explorebar from "@/components/explorebar";
8 |
9 | const DashboardPage = async () => {
10 | const session = await auth();
11 |
12 | return ;
13 | };
14 |
15 | export default DashboardPage;
16 |
--------------------------------------------------------------------------------
/app/dashboard/feed/getfeed.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "@/auth";
2 | import { prisma } from "@/lib/db";
3 | export async function GetFeed() {
4 | const session = await auth();
5 | const userEmail = session?.user?.email;
6 |
7 | if (userEmail) {
8 | const feed = await prisma.posts.findMany({});
9 | if (feed) {
10 | return feed;
11 | }
12 | }
13 | return [
14 | {
15 | id: 1,
16 | description: "string",
17 | imgUrl: "string",
18 | userId: "string",
19 | like: 1,
20 | },
21 | ];
22 | }
23 |
--------------------------------------------------------------------------------
/.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 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 | .env
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/app/api/user/getfeed/route.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "@/auth";
2 | import { prisma } from "@/lib/db";
3 | export async function GET() {
4 | const session = await auth();
5 | const userEmail = session?.user?.email;
6 |
7 | if (userEmail) {
8 | const feed = await prisma.posts.findMany({});
9 | if (feed) {
10 | return Response.json(feed);
11 | }
12 | }
13 | return Response.json([
14 | {
15 | id: 1,
16 | description: "string",
17 | imgUrl: "string",
18 | userId: "string",
19 | like: 1,
20 | },
21 | ]);
22 | }
23 |
--------------------------------------------------------------------------------
/prisma/migrations/20240427221532_added/migration.sql:
--------------------------------------------------------------------------------
1 | -- CreateTable
2 | CREATE TABLE "Resources" (
3 | "id" SERIAL NOT NULL,
4 | "title" TEXT NOT NULL,
5 | "description" TEXT NOT NULL,
6 | "userId" TEXT NOT NULL,
7 | "catogary" TEXT NOT NULL,
8 | "upvotes" TEXT[],
9 | "resourceLink" TEXT NOT NULL,
10 |
11 | CONSTRAINT "Resources_pkey" PRIMARY KEY ("id")
12 | );
13 |
14 | -- AddForeignKey
15 | ALTER TABLE "Resources" ADD CONSTRAINT "Resources_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
16 |
--------------------------------------------------------------------------------
/prisma/migrations/20240427225515_modefied/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `catogary` on the `Resources` table. All the data in the column will be lost.
5 | - You are about to drop the column `upvotes` on the `Resources` table. All the data in the column will be lost.
6 | - Added the required column `categary` to the `Resources` table without a default value. This is not possible if the table is not empty.
7 |
8 | */
9 | -- AlterTable
10 | ALTER TABLE "Resources" DROP COLUMN "catogary",
11 | DROP COLUMN "upvotes",
12 | ADD COLUMN "categary" TEXT NOT NULL;
13 |
--------------------------------------------------------------------------------
/prisma/migrations/20240424202227_init/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `commentId` on the `Posts` table. All the data in the column will be lost.
5 | - You are about to drop the `Comments` table. If the table is not empty, all the data it contains will be lost.
6 |
7 | */
8 | -- DropForeignKey
9 | ALTER TABLE "Comments" DROP CONSTRAINT "Comments_userId_fkey";
10 |
11 | -- DropForeignKey
12 | ALTER TABLE "Posts" DROP CONSTRAINT "Posts_commentId_fkey";
13 |
14 | -- AlterTable
15 | ALTER TABLE "Posts" DROP COLUMN "commentId";
16 |
17 | -- DropTable
18 | DROP TABLE "Comments";
19 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Inter } from "next/font/google";
3 | import "./globals.css";
4 | import { Providers } from "./providers";
5 | import { siteConfig } from "@/config/site-config";
6 |
7 | const inter = Inter({ subsets: ["latin"] });
8 |
9 | export const metadata: Metadata = siteConfig;
10 |
11 | export default function RootLayout({
12 | children,
13 | }: Readonly<{
14 | children: React.ReactNode;
15 | }>) {
16 | return (
17 |
18 |
19 | {children}
20 |
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/utils/verification-token.ts:
--------------------------------------------------------------------------------
1 | import { prisma } from "@/lib/db";
2 | export const getVerificationTokenByEmail = async (email: string) => {
3 | const verificationToken = await prisma.verificationToken.findFirst({
4 | where: {
5 | email,
6 | },
7 | });
8 |
9 | return verificationToken;
10 | };
11 |
12 | export const getVerificationTokenByToken = async (token: string) => {
13 | try {
14 | const verificationToken = await prisma.verificationToken.findUnique({
15 | where: {
16 | token,
17 | },
18 | });
19 |
20 | return verificationToken;
21 | } catch (error) {
22 | return null;
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/utils/user.ts:
--------------------------------------------------------------------------------
1 | import { prisma } from "@/lib/db";
2 |
3 | export const getUserByEmail = async (email: string) => {
4 | try {
5 | const user = await prisma.user.findUnique({
6 | where: {
7 | email,
8 | },
9 | });
10 | if (user) {
11 | return user;
12 | }
13 | } catch (error) {
14 | return error;
15 | }
16 | };
17 |
18 | export const getUserById = async (id: string) => {
19 | try {
20 | const user = prisma.user.findUnique({
21 | where: {
22 | id,
23 | },
24 | });
25 | if (user) {
26 | return user;
27 | }
28 | } catch (error) {
29 | return error;
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/auth.config.ts:
--------------------------------------------------------------------------------
1 | import type { NextAuthConfig } from "next-auth";
2 | import EmailProvider from "next-auth/providers/nodemailer";
3 | import Resend from "next-auth/providers/resend";
4 |
5 | export default {
6 | providers: [Resend({ from: "no-reply@unsight.club" })],
7 | } satisfies NextAuthConfig;
8 |
9 | // EmailProvider({
10 | // id: "email",
11 | // name: "email",
12 | // server: {
13 | // host: process.env.EMAIL_SERVER_HOST,
14 | // port: process.env.EMAIL_SERVER_PORT,
15 | // auth: {
16 | // user: process.env.EMAIL_SERVER_USER,
17 | // pass: process.env.EMAIL_SERVER_PASSWORD,
18 | // },
19 | // },
20 | // from: process.env.EMAIL_FROM,
21 | // }),
22 |
--------------------------------------------------------------------------------
/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 | "@/*": ["./*"]
22 | }
23 | },
24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
25 | "exclude": ["node_modules"]
26 | }
27 |
--------------------------------------------------------------------------------
/app/resources/aiml/getAIML.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "@/auth";
2 | import { prisma } from "@/lib/db";
3 |
4 | export async function GetAIML() {
5 | const session = await auth();
6 | const userEmail = session?.user?.email;
7 | if (userEmail) {
8 | const devOpsResources = await prisma.resources.findMany({
9 | where: {
10 | categary: "aiml",
11 | },
12 | });
13 | if (devOpsResources) {
14 | return devOpsResources;
15 | }
16 | }
17 | return [
18 | {
19 | id: 1,
20 | title: "string",
21 | description: "string",
22 | userId: "string",
23 | catogary: "aiml",
24 | upvotes: [""],
25 | resourceLink: "string",
26 | },
27 | ];
28 | }
29 |
--------------------------------------------------------------------------------
/app/resources/devops/getDevOps.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "@/auth";
2 | import { prisma } from "@/lib/db";
3 |
4 | export async function GetDevOps() {
5 | const session = await auth();
6 | const userEmail = session?.user?.email;
7 | if (userEmail) {
8 | const devOpsResources = await prisma.resources.findMany({
9 | where: {
10 | categary: "devops",
11 | },
12 | });
13 | if (devOpsResources) {
14 | return devOpsResources;
15 | }
16 | }
17 | return [
18 | {
19 | id: 1,
20 | title: "string",
21 | description: "string",
22 | userId: "string",
23 | catogary: "devops",
24 | upvotes: [""],
25 | resourceLink: "string",
26 | },
27 | ];
28 | }
29 |
--------------------------------------------------------------------------------
/app/resources/webdev/getWebDev.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "@/auth";
2 | import { prisma } from "@/lib/db";
3 |
4 | export const GetWebDev = async () => {
5 | const session = await auth();
6 | const userEmail = session?.user?.email;
7 | if (userEmail) {
8 | const webDevResources = await prisma.resources.findMany({
9 | where: {
10 | categary: "webdev",
11 | },
12 | });
13 | if (webDevResources) {
14 | return webDevResources;
15 | }
16 | }
17 | return [
18 | {
19 | id: 1,
20 | title: "string",
21 | description: "string",
22 | userId: "string",
23 | catogary: "webdev",
24 | upvotes: [""],
25 | resourceLink: "string",
26 | },
27 | ];
28 | };
29 |
--------------------------------------------------------------------------------
/auth.ts:
--------------------------------------------------------------------------------
1 | import NextAuth from "next-auth";
2 | import authConfig from "./auth.config";
3 | import { PrismaAdapter } from "@auth/prisma-adapter";
4 | import { prisma } from "@/lib/db";
5 |
6 | export const {
7 | handlers: { GET, POST },
8 | auth,
9 | signIn,
10 | signOut,
11 | } = NextAuth({
12 | callbacks: {
13 | async session({ token, session }) {
14 | console.log("Session Token", token);
15 |
16 | return session;
17 | },
18 | async jwt({ token }) {
19 | console.log("JWT Token", token);
20 | return token;
21 | },
22 | },
23 | adapter: PrismaAdapter(prisma),
24 | session: {
25 | strategy: "jwt",
26 | },
27 | ...authConfig,
28 | pages: {
29 | signIn: "/signIn",
30 | },
31 | });
32 |
--------------------------------------------------------------------------------
/app/resources/blockchain/getBlockchain.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "@/auth";
2 | import { prisma } from "@/lib/db";
3 |
4 | export async function GetBlockchain() {
5 | const session = await auth();
6 | const userEmail = session?.user?.email;
7 | if (userEmail) {
8 | const devOpsResources = await prisma.resources.findMany({
9 | where: {
10 | categary: "blockchain",
11 | },
12 | });
13 | if (devOpsResources) {
14 | return devOpsResources;
15 | }
16 | }
17 | return [
18 | {
19 | id: 1,
20 | title: "string",
21 | description: "string",
22 | userId: "string",
23 | catogary: "blockchain",
24 | upvotes: [""],
25 | resourceLink: "string",
26 | },
27 | ];
28 | }
29 |
--------------------------------------------------------------------------------
/lib/resend.ts:
--------------------------------------------------------------------------------
1 | import { Resend } from "resend";
2 |
3 | const resend = new Resend(process.env.RESEND_API_KEY);
4 |
5 | export const sendVerificationEmail = async (email: string, token: string) => {
6 | // const confirmLink = `http://localhost:3000/auth/new-verification?token=${token}`;
7 | const confirmLink =
8 | process.env.NODE_ENV === "development"
9 | ? `http://localhost:3000/auth/new-verification?token=${token}`
10 | : `https://www.unsight.club/auth/new-verification?token=${token}`;
11 |
12 | await resend.emails.send({
13 | from: "onboarding@unsight.club",
14 | to: email,
15 | subject: "Confirm your email",
16 | html: `Click here to confirm your email.
`,
17 | });
18 | };
19 |
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import Image from "next/image";
3 | import { Button } from "@/components/ui/button";
4 | import Link from "next/link";
5 | import { auth } from "@/auth";
6 | import { signOut } from "next-auth/react";
7 | import { useSession } from "next-auth/react";
8 | import Navbar from "@/components/navbar";
9 | import Landing from "@/components/landing";
10 | import Mainpage from "@/components/mainpage/mainpage";
11 | import Update from "@/components/Update";
12 |
13 | export default function Home() {
14 | // const session = useSession();
15 | return (
16 |
17 | {/*
18 |
19 |
*/}
20 |
21 |
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/app/dashboard/profile/userposts.ts:
--------------------------------------------------------------------------------
1 | import { auth } from "@/auth";
2 | import { prisma } from "@/lib/db";
3 |
4 | export default async function UserPosts() {
5 | const session = await auth();
6 | const userEmail = session?.user?.email;
7 |
8 | if (userEmail) {
9 | const user = await prisma.user.findUnique({
10 | where: {
11 | email: userEmail,
12 | },
13 | });
14 | if (user) {
15 | const posts = await prisma.posts.findMany({
16 | where: {
17 | userId: user.id,
18 | },
19 | });
20 | if (posts) {
21 | return posts;
22 | }
23 | }
24 | }
25 | return [
26 | {
27 | id: 1,
28 | description: "string",
29 | imgUrl: "null",
30 | userId: "string",
31 | like: 1,
32 | },
33 | ];
34 | }
35 |
--------------------------------------------------------------------------------
/app/resources/aiml/page.tsx:
--------------------------------------------------------------------------------
1 | import ResourceCard from "../resourcecard";
2 | import { GetAIML } from "./getAIML";
3 | import Reveal from "@/components/reveal";
4 | export default async function AIML() {
5 | const AIMLResources = await GetAIML();
6 | return (
7 |
8 | {AIMLResources.map((e, key) => {
9 | return (
10 |
11 |
20 |
21 | );
22 | })}
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/resources/all/page.tsx:
--------------------------------------------------------------------------------
1 | import ResourceCard from "../resourcecard";
2 | import { GetAllResources } from "./getall";
3 | import Reveal from "@/components/reveal";
4 | export default async function AllResources() {
5 | const resources = await GetAllResources();
6 | return (
7 |
8 | {resources.map((e, key) => {
9 | return (
10 |
11 |
20 |
21 | );
22 | })}
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/lib/token.ts:
--------------------------------------------------------------------------------
1 | import { getVerificationTokenByEmail } from "@/utils/verification-token";
2 | import { v4 as uuidv4 } from "uuid";
3 | import { prisma } from "@/lib/db";
4 | export const generateVerificationToken = async (email: string) => {
5 | const token = uuidv4();
6 | const expires = new Date(new Date().getTime() + 2 * 60 * 60 * 1000); // 2 hours
7 |
8 | const existingToken = await getVerificationTokenByEmail(email);
9 |
10 | if (existingToken) {
11 | await prisma.verificationToken.delete({
12 | where: {
13 | identifier_token: existingToken,
14 | },
15 | });
16 | }
17 |
18 | const verificationToken = await prisma.verificationToken.create({
19 | data: {
20 | identifier: token,
21 | email,
22 | token,
23 | expires,
24 | },
25 | });
26 |
27 | return verificationToken;
28 | };
29 |
--------------------------------------------------------------------------------
/app/resources/devops/page.tsx:
--------------------------------------------------------------------------------
1 | import { GetDevOps } from "./getDevOps";
2 | import ResourceCard from "../resourcecard";
3 | import Reveal from "@/components/reveal";
4 |
5 | export default async function Devops() {
6 | const DevOpsResources = await GetDevOps();
7 | return (
8 |
9 | {DevOpsResources.map((e, key) => {
10 | return (
11 |
12 |
21 |
22 | );
23 | })}
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/app/resources/webdev/page.tsx:
--------------------------------------------------------------------------------
1 | import Reveal from "@/components/reveal";
2 | import ResourceCard from "../resourcecard";
3 | import { GetWebDev } from "./getWebDev";
4 |
5 | export default async function WebDev() {
6 | const WebDevResources = await GetWebDev();
7 | return (
8 |
9 | {WebDevResources.map((e, key) => {
10 | return (
11 |
12 |
21 |
22 | );
23 | })}
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/app/resources/blockchain/page.tsx:
--------------------------------------------------------------------------------
1 | import { GetBlockchain } from "./getBlockchain";
2 | import ResourceCard from "../resourcecard";
3 | import Reveal from "@/components/reveal";
4 |
5 | export default async function Blockchain() {
6 | const Web3Resources = await GetBlockchain();
7 | return (
8 |
9 | {Web3Resources.map((e, key) => {
10 | return (
11 |
12 |
21 |
22 | );
23 | })}
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/components/mainpage/featureCard.tsx:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 |
3 | export default function FeatureCard({
4 | topText,
5 | svg,
6 | description,
7 | }: {
8 | topText: string;
9 | svg: React.ReactNode;
10 | description: string;
11 | }) {
12 | return (
13 |
14 |
15 | {topText}
16 |
17 |
18 |
{svg}
19 |
20 | {description}
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/app/dashboard/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Inter, Kanit } from "next/font/google";
3 | import Sidebar from "@/components/sidebar";
4 | import Landing from "@/components/landing";
5 | import Explorebar from "@/components/explorebar";
6 | import Navbar from "@/components/navbar";
7 |
8 | const inter = Inter({ subsets: ["latin"] });
9 | const kanit = Kanit({ subsets: ["latin"], weight: "400" });
10 |
11 | export const metadata: Metadata = {
12 | title: "Unsight",
13 | description: "Share your thoughts freely",
14 | };
15 |
16 | export default function RootLayout({
17 | children,
18 | }: Readonly<{
19 | children: React.ReactNode;
20 | }>) {
21 | return (
22 | <>
23 |
24 |
25 |
26 | {children}
27 |
28 |
29 | >
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/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 {}
7 |
8 | const Input = React.forwardRef(
9 | ({ className, type, ...props }, ref) => {
10 | return (
11 |
20 | )
21 | }
22 | )
23 | Input.displayName = "Input"
24 |
25 | export { Input }
26 |
--------------------------------------------------------------------------------
/app/api/user/createpost/route.ts:
--------------------------------------------------------------------------------
1 | import { NextRequest } from "next/server";
2 | import { auth } from "@/auth";
3 | import { prisma } from "@/lib/db";
4 |
5 | export async function POST(req: NextRequest) {
6 | const session = await auth();
7 | const { description } = await req.json();
8 | const userEmail = session?.user?.email;
9 |
10 | if (userEmail) {
11 | const user = await prisma.user.findUnique({
12 | where: {
13 | email: userEmail,
14 | },
15 | });
16 | if (user) {
17 | const post = await prisma.posts.create({
18 | data: {
19 | description: description,
20 | userId: user.id,
21 | },
22 | });
23 | if (post) {
24 | return Response.json(post);
25 | }
26 | }
27 | }
28 | return Response.json({
29 | id: "string",
30 | description: "string",
31 | imgUrl: "string ",
32 | userId: "string",
33 | like: "number ",
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/components/underdevelopment.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { Button } from "./ui/button";
3 | import Link from "next/link";
4 |
5 | export default function UnderDevelopment() {
6 | return (
7 |
8 |
9 |
10 | This page is under development!
11 |
12 |
13 | Soon You will see content over here, Till then please explore our
14 | other pages
15 |
16 |
17 |
18 | Go to Home!
19 |
20 |
21 |
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/components/ui/toaster.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import {
4 | Toast,
5 | ToastClose,
6 | ToastDescription,
7 | ToastProvider,
8 | ToastTitle,
9 | ToastViewport,
10 | } from "@/components/ui/toast"
11 | import { useToast } from "@/components/ui/use-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 |
--------------------------------------------------------------------------------
/app/api/user/likepost/route.ts:
--------------------------------------------------------------------------------
1 | import { NextRequest } from "next/server";
2 | import { auth } from "@/auth";
3 | import { prisma } from "@/lib/db";
4 | export async function POST(req: NextRequest) {
5 | const session = await auth();
6 | const userEmail = session?.user?.email;
7 | const { postId } = await req.json();
8 |
9 | if (userEmail) {
10 | const user = await prisma.user.findUnique({
11 | where: {
12 | email: userEmail,
13 | },
14 | });
15 | if (user) {
16 | const post = await prisma.posts.findFirst({
17 | where: {
18 | id: postId,
19 | },
20 | });
21 | if (post) {
22 | const likes = post.like;
23 | await prisma.posts.update({
24 | where: {
25 | id: postId,
26 | },
27 | data: {
28 | like: likes ? likes + 1 : 1,
29 | },
30 | });
31 | return Response.json(likes);
32 | }
33 | }
34 | }
35 | return Response.json(1);
36 | }
37 |
--------------------------------------------------------------------------------
/app/api/user/unlikepost/route.ts:
--------------------------------------------------------------------------------
1 | import { NextRequest } from "next/server";
2 | import { auth } from "@/auth";
3 | import { prisma } from "@/lib/db";
4 | export async function POST(req: NextRequest) {
5 | const session = await auth();
6 | const userEmail = session?.user?.email;
7 | const { postId } = await req.json();
8 |
9 | if (userEmail) {
10 | const user = await prisma.user.findUnique({
11 | where: {
12 | email: userEmail,
13 | },
14 | });
15 | if (user) {
16 | const post = await prisma.posts.findFirst({
17 | where: {
18 | id: postId,
19 | },
20 | });
21 | if (post) {
22 | const likes = post.like;
23 | await prisma.posts.update({
24 | where: {
25 | id: postId,
26 | },
27 | data: {
28 | like: likes ? likes - 1 : 0,
29 | },
30 | });
31 | return Response.json(likes);
32 | }
33 | }
34 | }
35 | return Response.json(1);
36 | }
37 |
--------------------------------------------------------------------------------
/app/resources/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Inter, Kanit } from "next/font/google";
3 | import Sidebar from "@/components/sidebar";
4 | import Landing from "@/components/landing";
5 | import Explorebar from "@/components/explorebar";
6 | import Navbar from "@/components/navbar";
7 | import SidePanel from "./sidepanel";
8 |
9 | const inter = Inter({ subsets: ["latin"] });
10 | const kanit = Kanit({ subsets: ["latin"], weight: "400" });
11 |
12 | export const metadata: Metadata = {
13 | title: "Unsight",
14 | description: "Share your thoughts freely",
15 | };
16 |
17 | export default function RootLayout({
18 | children,
19 | }: Readonly<{
20 | children: React.ReactNode;
21 | }>) {
22 | return (
23 | <>
24 |
25 |
26 |
27 |
{children}
28 |
29 |
30 | >
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/components/ui/sonner.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { useTheme } from "next-themes"
4 | import { Toaster as Sonner } from "sonner"
5 |
6 | type ToasterProps = React.ComponentProps
7 |
8 | const Toaster = ({ ...props }: ToasterProps) => {
9 | const { theme = "system" } = useTheme()
10 |
11 | return (
12 |
28 | )
29 | }
30 |
31 | export { Toaster }
32 |
--------------------------------------------------------------------------------
/components/reveal.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useEffect, useRef } from "react";
3 | import { motion, useInView, useAnimation } from "framer-motion";
4 |
5 | interface Props {
6 | children: JSX.Element;
7 | width?: "fit-content" | "100%";
8 | }
9 |
10 | export default function Reveal({ children, width = "fit-content" }: Props) {
11 | const ref = useRef(null);
12 | const isInView = useInView(ref, { once: true });
13 | const mainControls = useAnimation();
14 |
15 | useEffect(() => {
16 | if (isInView) {
17 | mainControls.start("visible");
18 | }
19 | }, [isInView, mainControls]);
20 | return (
21 |
22 |
31 | {children}
32 |
33 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/prisma/migrations/20240424183057_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- CreateTable
2 | CREATE TABLE "Posts" (
3 | "id" TEXT NOT NULL,
4 | "description" TEXT NOT NULL,
5 | "imgUrl" TEXT,
6 | "userId" TEXT NOT NULL,
7 | "like" INTEGER,
8 | "commentId" TEXT NOT NULL,
9 |
10 | CONSTRAINT "Posts_pkey" PRIMARY KEY ("id")
11 | );
12 |
13 | -- CreateTable
14 | CREATE TABLE "Comments" (
15 | "id" TEXT NOT NULL,
16 | "content" TEXT NOT NULL,
17 | "imgUrl" TEXT,
18 | "userId" TEXT NOT NULL,
19 | "like" INTEGER,
20 |
21 | CONSTRAINT "Comments_pkey" PRIMARY KEY ("id")
22 | );
23 |
24 | -- AddForeignKey
25 | ALTER TABLE "Posts" ADD CONSTRAINT "Posts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
26 |
27 | -- AddForeignKey
28 | ALTER TABLE "Posts" ADD CONSTRAINT "Posts_commentId_fkey" FOREIGN KEY ("commentId") REFERENCES "Comments"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
29 |
30 | -- AddForeignKey
31 | ALTER TABLE "Comments" ADD CONSTRAINT "Comments_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
32 |
--------------------------------------------------------------------------------
/app/api/user/addresourse/route.ts:
--------------------------------------------------------------------------------
1 | import { NextRequest } from "next/server";
2 | import { auth } from "@/auth";
3 | import { prisma } from "@/lib/db";
4 |
5 | export async function POST(req: NextRequest) {
6 | const session = await auth();
7 |
8 | const { title, description, categary, resourceLink } = await req.json();
9 |
10 | const userEmail = session?.user?.email;
11 |
12 | if (userEmail) {
13 | const user = await prisma.user.findUnique({
14 | where: {
15 | email: userEmail,
16 | },
17 | });
18 | if (user) {
19 | const post = await prisma.resources.create({
20 | data: {
21 | title: title,
22 | description: description,
23 | userId: user.id,
24 | categary: categary,
25 | resourceLink: resourceLink,
26 | },
27 | });
28 | if (post) {
29 | return Response.json(post);
30 | }
31 | }
32 | }
33 | return Response.json({
34 | id: 1,
35 | title: "string",
36 | description: "string",
37 | userId: "string",
38 | catogary: "string",
39 | upvotes: [""],
40 | resourceLink: "string",
41 | });
42 | }
43 |
--------------------------------------------------------------------------------
/app/dashboard/profile/page.tsx:
--------------------------------------------------------------------------------
1 | import Landing from "@/components/landing";
2 | import ProfilePage from "@/components/user/profile";
3 | import UserPosts from "./userposts";
4 | import { Posts } from "../feed/posts";
5 | import Reveal from "@/components/reveal";
6 |
7 | export default async function Profile() {
8 | const posts = await UserPosts();
9 | return (
10 |
11 |
12 |
13 |
14 | {posts.map((e, key) => {
15 | return (
16 |
17 |
27 |
28 | );
29 | })}
30 |
31 |
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/actions/register.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import * as z from "zod";
4 | import { prisma } from "@/lib/db";
5 | import { RegisterSchema } from "@/schema";
6 | import bcrypt from "bcrypt";
7 | import { getUserByEmail } from "@/utils/user";
8 | import { generateVerificationToken } from "@/lib/token";
9 | import { sendVerificationEmail } from "@/lib/resend";
10 |
11 | export const register = async (values: z.infer) => {
12 | const isValid = RegisterSchema.safeParse(values);
13 | console.log("isValid", isValid);
14 |
15 | if (!isValid.success) {
16 | return { error: "Email is not valid" };
17 | }
18 |
19 | const { email, password, name } = isValid.data;
20 |
21 | const hashedPassword = await bcrypt.hash(password, 10);
22 |
23 | const existingUser = await getUserByEmail(email);
24 |
25 | if (existingUser) {
26 | return { error: "User already exists" };
27 | }
28 |
29 | await prisma.user.create({
30 | data: {
31 | email,
32 | password: hashedPassword,
33 | name,
34 | },
35 | });
36 |
37 | const verificationToken = await generateVerificationToken(email);
38 |
39 | await sendVerificationEmail(email, verificationToken.token);
40 |
41 | return { success: "Confirmation Email Sent" };
42 | };
43 |
--------------------------------------------------------------------------------
/app/dashboard/feed/page.tsx:
--------------------------------------------------------------------------------
1 | import { Input } from "@/components/ui/input";
2 | import { Card } from "@/components/ui/card";
3 | import PostCard from "@/components/postCard";
4 | import { useEffect, useState } from "react";
5 | import axios from "axios";
6 | import { useRouter } from "next/navigation";
7 | import z from "zod";
8 | import { Posts } from "./posts";
9 | import { GetFeed } from "./getfeed";
10 | import PostPanel from "@/components/user/postPanel";
11 | import Reveal from "@/components/reveal";
12 |
13 | export default async function Feed() {
14 | const feed = await GetFeed();
15 | return (
16 |
17 |
18 |
19 | {feed.map((e, key) => {
20 | return (
21 |
22 |
32 |
33 | );
34 | })}
35 |
36 |
37 | );
38 | }
39 |
--------------------------------------------------------------------------------
/components/postCard.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from "./ui/card";
2 |
3 | export default function PostCard() {
4 | return (
5 |
6 |
7 |
12 |
13 |
Politics
14 |
ex-SpaceX
15 |
16 |
17 |
18 | Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quia, quas!
19 |
20 |
21 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Mollitia alias
22 | eos iusto natus ipsum. Cum quasi iure reprehenderit minus quis?
23 |
24 |
25 |
26 | h
27 |
28 |
29 | h
30 |
31 |
32 | h
33 |
34 |
35 |
36 | );
37 | }
38 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/actions/login.ts:
--------------------------------------------------------------------------------
1 | "use server";
2 |
3 | import { LoginSchema } from "@/schema";
4 | import { z } from "zod";
5 | import { signIn } from "@/auth";
6 | import { prisma } from "@/lib/db";
7 | import { universities } from "./domains";
8 |
9 | export const login = async (values: z.infer) => {
10 | const confirmationLink =
11 | process.env.NODE_ENV === "development"
12 | ? "http://localhost:3000/confirm-email"
13 | : "https://www.unsight.club/confirm-email";
14 | const clgEmails = universities;
15 |
16 | // Check to see if data is valid
17 |
18 | const isValid = LoginSchema.safeParse(values);
19 | console.log(isValid);
20 |
21 | if (!isValid.success) {
22 | throw new Error("Email is not valid");
23 | }
24 |
25 | const { email } = isValid.data;
26 |
27 | if (email) {
28 | for (let i = 0; i < clgEmails.length; i++) {
29 | if (clgEmails[i] == email.split("@")[1]) {
30 | await signIn("resend", { email, redirect: false });
31 | return { success: `Email sent to ${email}` };
32 | }
33 | }
34 | throw Error("Invalid Email, use College Email: " + email);
35 | }
36 | // if (email.indexOf("gmail.com") >= 0) {
37 | // throw new Error("Write your clg email");
38 | // }
39 |
40 | // signIn("email", { email, redirectTo: "/dashboard/feed" });\
41 | return { Msg: `Provide valid email` };
42 | };
43 |
--------------------------------------------------------------------------------
/prisma/migrations/20240424202049_init/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - The primary key for the `Comments` table will be changed. If it partially fails, the table could be left without primary key constraint.
5 | - The `id` column on the `Comments` table would be dropped and recreated. This will lead to data loss if there is data in the column.
6 | - The primary key for the `Posts` table will be changed. If it partially fails, the table could be left without primary key constraint.
7 | - The `id` column on the `Posts` table would be dropped and recreated. This will lead to data loss if there is data in the column.
8 | - Added the required column `commentId` to the `Posts` table without a default value. This is not possible if the table is not empty.
9 |
10 | */
11 | -- DropForeignKey
12 | ALTER TABLE "Posts" DROP CONSTRAINT "Posts_commentId_fkey";
13 |
14 | -- AlterTable
15 | ALTER TABLE "Comments" DROP CONSTRAINT "Comments_pkey",
16 | DROP COLUMN "id",
17 | ADD COLUMN "id" SERIAL NOT NULL,
18 | ADD CONSTRAINT "Comments_pkey" PRIMARY KEY ("id");
19 |
20 | -- AlterTable
21 | ALTER TABLE "Posts" DROP CONSTRAINT "Posts_pkey",
22 | DROP COLUMN "id",
23 | ADD COLUMN "id" SERIAL NOT NULL,
24 | DROP COLUMN "commentId",
25 | ADD COLUMN "commentId" INTEGER NOT NULL,
26 | ADD CONSTRAINT "Posts_pkey" PRIMARY KEY ("id");
27 |
28 | -- AddForeignKey
29 | ALTER TABLE "Posts" ADD CONSTRAINT "Posts_commentId_fkey" FOREIGN KEY ("commentId") REFERENCES "Comments"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
30 |
--------------------------------------------------------------------------------
/components/auth/sideSection.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 |
3 | export default function SideSection() {
4 | return (
5 |
6 |
7 |
8 |
13 |
14 | Unsight
15 |
16 |
17 |
18 |
19 |
Welcome to Unsight
20 |
21 | A platform where you can freely share your thoughts all across the
22 | world, without revealing your identity
23 |
24 |
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/components/mainpage/mainpagetitle.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "../ui/button";
2 | import Reveal from "../reveal";
3 | import Link from "next/link";
4 |
5 | export default function MainpageTitle() {
6 | return (
7 |
8 |
9 |
10 | Building Trust!
11 |
12 |
13 |
14 |
15 | with Anonymity
16 |
17 |
18 |
19 |
20 | Welcome to Unsight, a platform where you can...
21 |
22 |
23 |
24 |
25 | Explore, Connect, and Share With Confidence
26 |
27 |
28 |
29 |
30 |
31 |
32 | Join Today
33 |
34 |
35 |
36 |
37 | );
38 | }
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "unsight",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "postinstall": "prisma generate",
9 | "start": "next start",
10 | "lint": "next lint"
11 | },
12 | "dependencies": {
13 | "@auth/prisma-adapter": "^2.0.0",
14 | "@radix-ui/react-label": "^2.0.2",
15 | "@radix-ui/react-slot": "^1.0.2",
16 | "@radix-ui/react-toast": "^1.1.5",
17 | "@react-email/components": "0.0.16",
18 | "@types/bcrypt": "^5.0.2",
19 | "@types/uuid": "^9.0.8",
20 | "bcrypt": "^5.1.1",
21 | "class-variance-authority": "^0.7.0",
22 | "clsx": "^2.1.0",
23 | "framer-motion": "^11.1.7",
24 | "link-preview-js": "^3.0.5",
25 | "lucide-react": "^0.372.0",
26 | "next": "^14.2.3",
27 | "next-auth": "^5.0.0-beta.16",
28 | "next-themes": "^0.3.0",
29 | "nodemailer": "^6.9.13",
30 | "react": "^18",
31 | "react-dom": "^18",
32 | "react-email": "^1.10.1",
33 | "react-hook-form": "^7.51.3",
34 | "resend": "^3.2.0",
35 | "sonner": "^1.4.41",
36 | "tailwind-merge": "^2.3.0",
37 | "tailwind-scrollbar-hide": "^1.1.7",
38 | "tailwindcss-animate": "^1.0.7",
39 | "uuid": "^9.0.1",
40 | "zod": "^3.22.5"
41 | },
42 | "devDependencies": {
43 | "@hookform/resolvers": "^3.3.4",
44 | "@prisma/client": "^5.12.1",
45 | "@types/node": "^20",
46 | "@types/react": "^18",
47 | "@types/react-dom": "^18",
48 | "axios": "^1.6.8",
49 | "eslint": "^8",
50 | "eslint-config-next": "14.2.2",
51 | "postcss": "^8",
52 | "prisma": "^5.12.1",
53 | "tailwindcss": "^3.4.1"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/config/site-config.ts:
--------------------------------------------------------------------------------
1 | import { Metadata } from "next";
2 |
3 | const TITLE = "Unsight - Join the global community of students!";
4 | const DESCRIPTION =
5 | "Interact in a global community of students. share thoughts, opportunities, resources and more, freely keeping your identity anonymous.";
6 |
7 | const PREVIEW_IMAGE_URL = "https://www.unsight.club/opengraph-image.png";
8 | const ALT_TITLE =
9 | "Unsight - Join the global community of students with Anonymity";
10 | const BASE_URL = "https://www.unsight.club";
11 |
12 | export const siteConfig: Metadata = {
13 | title: TITLE,
14 | description: DESCRIPTION,
15 | icons: {
16 | icon: "/favicon.ico",
17 | },
18 | applicationName: "Unsight",
19 | creator: "Kartikey",
20 | twitter: {
21 | creator: "@KartikeyStack",
22 | title: TITLE,
23 | description: DESCRIPTION,
24 | card: "summary_large_image",
25 | images: [
26 | {
27 | url: PREVIEW_IMAGE_URL,
28 | width: 1200,
29 | height: 630,
30 | alt: ALT_TITLE,
31 | },
32 | ],
33 | },
34 | openGraph: {
35 | title: TITLE,
36 | description: DESCRIPTION,
37 | siteName: "Unsight",
38 | url: BASE_URL,
39 | locale: "en_US",
40 | type: "website",
41 | images: [
42 | {
43 | url: PREVIEW_IMAGE_URL,
44 | width: 1200,
45 | height: 630,
46 | alt: ALT_TITLE,
47 | },
48 | ],
49 | },
50 | category: "Technology",
51 | alternates: {
52 | canonical: BASE_URL,
53 | },
54 | keywords: [
55 | "Unsight",
56 | "Team Blind",
57 | "Club",
58 | "Kartikey Verma app",
59 | "Community",
60 | "Anonymous",
61 | "Anonymity",
62 | "Share your thoughts freely",
63 | "Students community",
64 | ],
65 | metadataBase: new URL(BASE_URL),
66 | };
67 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | body {
7 | background-color: black;
8 | }
9 | :root {
10 | --background: 0 0% 100%;
11 | --foreground: 222.2 84% 4.9%;
12 | scroll-behavior: smooth;
13 |
14 | --card: 0 0% 100%;
15 | --card-foreground: 222.2 84% 4.9%;
16 |
17 | --popover: 0 0% 100%;
18 | --popover-foreground: 222.2 84% 4.9%;
19 |
20 | --primary: 222.2 47.4% 11.2%;
21 | --primary-foreground: 210 40% 98%;
22 |
23 | --secondary: 210 40% 96.1%;
24 | --secondary-foreground: 222.2 47.4% 11.2%;
25 |
26 | --muted: 210 40% 96.1%;
27 | --muted-foreground: 215.4 16.3% 46.9%;
28 |
29 | --accent: 210 40% 96.1%;
30 | --accent-foreground: 222.2 47.4% 11.2%;
31 |
32 | --destructive: 0 84.2% 60.2%;
33 | --destructive-foreground: 210 40% 98%;
34 |
35 | --border: 214.3 31.8% 91.4%;
36 | --input: 214.3 31.8% 91.4%;
37 | --ring: 222.2 84% 4.9%;
38 |
39 | --radius: 0.5rem;
40 | }
41 |
42 | .dark {
43 | scroll-behavior: smooth;
44 | --background: 222.2 84% 4.9%;
45 | --foreground: 210 40% 98%;
46 |
47 | --card: 222.2 84% 4.9%;
48 | --card-foreground: 210 40% 98%;
49 |
50 | --popover: 222.2 84% 4.9%;
51 | --popover-foreground: 210 40% 98%;
52 |
53 | --primary: 210 40% 98%;
54 | --primary-foreground: 222.2 47.4% 11.2%;
55 |
56 | --secondary: 217.2 32.6% 17.5%;
57 | --secondary-foreground: 210 40% 98%;
58 |
59 | --muted: 217.2 32.6% 17.5%;
60 | --muted-foreground: 215 20.2% 65.1%;
61 |
62 | --accent: 217.2 32.6% 17.5%;
63 | --accent-foreground: 210 40% 98%;
64 |
65 | --destructive: 0 62.8% 30.6%;
66 | --destructive-foreground: 210 40% 98%;
67 |
68 | --border: 217.2 32.6% 17.5%;
69 | --input: 217.2 32.6% 17.5%;
70 | --ring: 212.7 26.8% 83.9%;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/components/explorebar.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from "./ui/card";
2 |
3 | export default function Explorebar() {
4 | return (
5 |
6 |
7 | sponsored
8 |
9 |
10 | Popular posts
11 |
12 |
13 |
14 |
Design Career
15 |
16 |
145
17 |
18 |
19 | UX Design and Product Design Job Market
20 |
21 |
22 |
23 |
24 |
25 |
26 |
Web3 Career
27 |
28 |
8k
29 |
30 |
Solana or Ethereum Ecosystem
31 |
32 |
33 |
34 |
35 |
36 |
Personal Finance
37 |
38 |
1145
39 |
40 |
How to do car insurance
41 |
42 |
43 |
44 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/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 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
9 | {
10 | variants: {
11 | variant: {
12 | default: "bg-primary text-primary-foreground hover:bg-primary/90",
13 | destructive:
14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90",
15 | outline:
16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17 | secondary:
18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80",
19 | ghost: "hover:bg-accent hover:text-accent-foreground",
20 | link: "text-primary underline-offset-4 hover:underline",
21 | },
22 | size: {
23 | default: "h-10 px-4 py-2",
24 | sm: "h-9 rounded-md px-3",
25 | lg: "h-11 rounded-md px-8",
26 | icon: "h-10 w-10",
27 | },
28 | },
29 | defaultVariants: {
30 | variant: "default",
31 | size: "default",
32 | },
33 | }
34 | )
35 |
36 | export interface ButtonProps
37 | extends React.ButtonHTMLAttributes,
38 | VariantProps {
39 | asChild?: boolean
40 | }
41 |
42 | const Button = React.forwardRef(
43 | ({ className, variant, size, asChild = false, ...props }, ref) => {
44 | const Comp = asChild ? Slot : "button"
45 | return (
46 |
51 | )
52 | }
53 | )
54 | Button.displayName = "Button"
55 |
56 | export { Button, buttonVariants }
57 |
--------------------------------------------------------------------------------
/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 |
44 | ))
45 | CardTitle.displayName = "CardTitle"
46 |
47 | const CardDescription = React.forwardRef<
48 | HTMLParagraphElement,
49 | React.HTMLAttributes
50 | >(({ className, ...props }, ref) => (
51 |
56 | ))
57 | CardDescription.displayName = "CardDescription"
58 |
59 | const CardContent = React.forwardRef<
60 | HTMLDivElement,
61 | React.HTMLAttributes
62 | >(({ className, ...props }, ref) => (
63 |
64 | ))
65 | CardContent.displayName = "CardContent"
66 |
67 | const CardFooter = React.forwardRef<
68 | HTMLDivElement,
69 | React.HTMLAttributes
70 | >(({ className, ...props }, ref) => (
71 |
76 | ))
77 | CardFooter.displayName = "CardFooter"
78 |
79 | export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
80 |
--------------------------------------------------------------------------------
/components/mainpage/imagebanner.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import Image from "next/image";
3 | import bg2 from "@/public/bg2.png";
4 | import bg1 from "@/public/bg1.png";
5 | import bg3 from "@/public/bg3.png";
6 | import { useEffect, useState, useMemo } from "react";
7 |
8 | export default function ImageBanner() {
9 | const [bannerImg, setBannerImg] = useState(bg1);
10 | const [index, setIndex] = useState(0);
11 | // const images = [bg1, bg2, bg3];
12 | const images = useMemo(() => [bg1, bg2, bg3], []);
13 |
14 | useEffect(() => {
15 | const intervalId = setInterval(() => {
16 | setIndex((prevIndex) => (prevIndex + 1) % images.length);
17 | }, 5000);
18 |
19 | return () => clearInterval(intervalId);
20 | }, [images]);
21 |
22 | useEffect(() => {
23 | setBannerImg(images[index]);
24 | }, [index, images]);
25 | return (
26 |
27 |
28 |
29 |
30 |
31 | {
34 | setBannerImg(bg1);
35 | }}
36 | >
37 | o
38 |
39 | {
42 | setBannerImg(bg2);
43 | }}
44 | >
45 | o
46 |
47 | {
50 | setBannerImg(bg3);
51 | }}
52 | >
53 | o
54 |
55 |
56 |
57 | );
58 | }
59 |
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const config = {
4 | darkMode: ["class"],
5 | content: [
6 | "./pages/**/*.{ts,tsx}",
7 | "./components/**/*.{ts,tsx}",
8 | "./app/**/*.{ts,tsx}",
9 | "./src/**/*.{ts,tsx}",
10 | ],
11 | prefix: "",
12 | theme: {
13 | container: {
14 | center: true,
15 | padding: "2rem",
16 | screens: {
17 | "2xl": "1400px",
18 | },
19 | },
20 | extend: {
21 | colors: {
22 | border: "hsl(var(--border))",
23 | input: "hsl(var(--input))",
24 | ring: "hsl(var(--ring))",
25 | background: "hsl(var(--background))",
26 | foreground: "hsl(var(--foreground))",
27 | primary: {
28 | DEFAULT: "hsl(var(--primary))",
29 | foreground: "hsl(var(--primary-foreground))",
30 | },
31 | secondary: {
32 | DEFAULT: "hsl(var(--secondary))",
33 | foreground: "hsl(var(--secondary-foreground))",
34 | },
35 | destructive: {
36 | DEFAULT: "hsl(var(--destructive))",
37 | foreground: "hsl(var(--destructive-foreground))",
38 | },
39 | muted: {
40 | DEFAULT: "hsl(var(--muted))",
41 | foreground: "hsl(var(--muted-foreground))",
42 | },
43 | accent: {
44 | DEFAULT: "hsl(var(--accent))",
45 | foreground: "hsl(var(--accent-foreground))",
46 | },
47 | popover: {
48 | DEFAULT: "hsl(var(--popover))",
49 | foreground: "hsl(var(--popover-foreground))",
50 | },
51 | card: {
52 | DEFAULT: "hsl(var(--card))",
53 | foreground: "hsl(var(--card-foreground))",
54 | },
55 | },
56 | borderRadius: {
57 | lg: "var(--radius)",
58 | md: "calc(var(--radius) - 2px)",
59 | sm: "calc(var(--radius) - 4px)",
60 | },
61 | keyframes: {
62 | "accordion-down": {
63 | from: { height: "0" },
64 | to: { height: "var(--radix-accordion-content-height)" },
65 | },
66 | "accordion-up": {
67 | from: { height: "var(--radix-accordion-content-height)" },
68 | to: { height: "0" },
69 | },
70 | },
71 | animation: {
72 | "accordion-down": "accordion-down 0.2s ease-out",
73 | "accordion-up": "accordion-up 0.2s ease-out",
74 | },
75 | },
76 | },
77 | plugins: [require("tailwindcss-animate"), require("tailwind-scrollbar-hide")],
78 | } satisfies Config;
79 |
80 | export default config;
81 |
--------------------------------------------------------------------------------
/prisma/migrations/20240421200423_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- CreateTable
2 | CREATE TABLE "User" (
3 | "id" TEXT NOT NULL,
4 | "name" TEXT,
5 | "email" TEXT NOT NULL,
6 | "emailVerified" TIMESTAMP(3),
7 | "image" TEXT,
8 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
9 | "updatedAt" TIMESTAMP(3) NOT NULL,
10 |
11 | CONSTRAINT "User_pkey" PRIMARY KEY ("id")
12 | );
13 |
14 | -- CreateTable
15 | CREATE TABLE "Account" (
16 | "userId" TEXT NOT NULL,
17 | "type" TEXT NOT NULL,
18 | "provider" TEXT NOT NULL,
19 | "providerAccountId" TEXT NOT NULL,
20 | "refresh_token" TEXT,
21 | "access_token" TEXT,
22 | "expires_at" INTEGER,
23 | "token_type" TEXT,
24 | "scope" TEXT,
25 | "id_token" TEXT,
26 | "session_state" TEXT,
27 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
28 | "updatedAt" TIMESTAMP(3) NOT NULL,
29 |
30 | CONSTRAINT "Account_pkey" PRIMARY KEY ("provider","providerAccountId")
31 | );
32 |
33 | -- CreateTable
34 | CREATE TABLE "Session" (
35 | "sessionToken" TEXT NOT NULL,
36 | "userId" TEXT NOT NULL,
37 | "expires" TIMESTAMP(3) NOT NULL,
38 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
39 | "updatedAt" TIMESTAMP(3) NOT NULL
40 | );
41 |
42 | -- CreateTable
43 | CREATE TABLE "VerificationToken" (
44 | "identifier" TEXT NOT NULL,
45 | "token" TEXT NOT NULL,
46 | "expires" TIMESTAMP(3) NOT NULL,
47 | "email" TEXT,
48 |
49 | CONSTRAINT "VerificationToken_pkey" PRIMARY KEY ("identifier","token")
50 | );
51 |
52 | -- CreateTable
53 | CREATE TABLE "Authenticator" (
54 | "id" TEXT NOT NULL,
55 | "credentialID" TEXT NOT NULL,
56 | "userId" TEXT NOT NULL,
57 | "providerAccountId" TEXT NOT NULL,
58 | "credentialPublicKey" TEXT NOT NULL,
59 | "counter" INTEGER NOT NULL,
60 | "credentialDeviceType" TEXT NOT NULL,
61 | "credentialBackedUp" BOOLEAN NOT NULL,
62 | "transports" TEXT,
63 |
64 | CONSTRAINT "Authenticator_pkey" PRIMARY KEY ("id")
65 | );
66 |
67 | -- CreateIndex
68 | CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
69 |
70 | -- CreateIndex
71 | CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken");
72 |
73 | -- CreateIndex
74 | CREATE UNIQUE INDEX "Authenticator_credentialID_key" ON "Authenticator"("credentialID");
75 |
76 | -- AddForeignKey
77 | ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
78 |
79 | -- AddForeignKey
80 | ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
81 |
82 | -- AddForeignKey
83 | ALTER TABLE "Authenticator" ADD CONSTRAINT "Authenticator_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
84 |
--------------------------------------------------------------------------------
/components/user/profile.tsx:
--------------------------------------------------------------------------------
1 | import Reveal from "../reveal";
2 |
3 | export default function ProfilePage({
4 | profileImg,
5 | name,
6 | bannerImg,
7 | id,
8 | }: {
9 | profileImg: string;
10 | name: string;
11 | bannerImg: string;
12 | id: string;
13 | }) {
14 | return (
15 |
16 |
17 |
18 |
23 |
24 |
25 |
26 |
27 |
32 |
33 |
34 |
35 | Kartikey Verma
36 |
37 |
38 |
39 |
44 |
48 |
49 |
Public
50 |
51 |
52 |
53 |
54 |
55 |
56 | Follow
57 |
58 |
59 |
60 |
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/components/landing.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { Input } from "./ui/input";
4 | import { Card } from "./ui/card";
5 | import PostCard from "./postCard";
6 | import { useState } from "react";
7 | import axios from "axios";
8 | import { useRouter } from "next/navigation";
9 | export default function Landing() {
10 | const router = useRouter();
11 | const [description, setPost] = useState("");
12 |
13 | const handleOnclick = async () => {
14 | try {
15 | const apiUrl =
16 | process.env.NODE_ENV === "development"
17 | ? "http://localhost:3000/api/user/createpost"
18 | : "https://www.unsight.club/api/user/createpost";
19 | const response = await axios.post(apiUrl, { description });
20 | console.log("el");
21 |
22 | router.push("/");
23 | return response.data;
24 | } catch (error) {
25 | return `Error: ${error}`;
26 | }
27 | };
28 |
29 | return (
30 |
31 |
32 |
33 | Unsight - Anonymous and Professional Community of Students
34 |
35 |
36 |
{
38 | setPost(e.target.value);
39 | }}
40 | className="h-16 text-xl bg-slate-300 rounded-xl w-[100%]"
41 | placeholder="Start a post..."
42 | />
43 |
47 |
52 |
53 |
58 |
59 |
60 |
61 |
65 |
66 |
67 |
68 |
69 |
75 |
76 | );
77 | }
78 |
--------------------------------------------------------------------------------
/app/resources/resourcecard.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { Button } from "@/components/ui/button";
3 | import { useEffect, useRef } from "react";
4 |
5 | export default function ResourceCard({
6 | id,
7 | userId,
8 | categary,
9 | title,
10 | description,
11 | resourceLink,
12 | }: {
13 | id: number;
14 | userId: string;
15 | categary: string;
16 | title: string;
17 | description: string;
18 | resourceLink: string;
19 | }) {
20 | const cardRef = useRef(null);
21 |
22 | useEffect(() => {
23 | if (typeof window !== "undefined") {
24 | const card = cardRef.current;
25 |
26 | const handleMouseMove = (e: MouseEvent) => {
27 | if (card) {
28 | const rect = card.getBoundingClientRect();
29 | const x = e.clientX - rect.left;
30 | const y = e.clientY - rect.top;
31 | card.style.setProperty("--x", `${x}px`);
32 | card.style.setProperty("--y", `${y}px`);
33 | }
34 | };
35 |
36 | card?.addEventListener("mousemove", handleMouseMove);
37 |
38 | return () => {
39 | card?.removeEventListener("mousemove", handleMouseMove);
40 | };
41 | }
42 | }, []);
43 |
44 | return (
45 |
49 |
50 |
{title}
51 |
{description}
52 |
53 |
54 | {categary}
55 |
56 |
71 |
72 |
99 |
100 | );
101 | }
102 |
--------------------------------------------------------------------------------
/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 = "postgresql"
13 | url = env("DATABASE_URL")
14 | }
15 |
16 | model User {
17 | id String @id @default(cuid())
18 | name String?
19 | email String @unique
20 | password String?
21 | emailVerified DateTime?
22 | image String?
23 | accounts Account[]
24 | sessions Session[]
25 | posts Posts[]
26 | // Optional for WebAuthn support
27 | Authenticator Authenticator[]
28 |
29 | createdAt DateTime @default(now())
30 | updatedAt DateTime @updatedAt
31 | Resources Resources[]
32 | }
33 |
34 | model Posts {
35 | id Int @id @default(autoincrement())
36 | description String
37 | imgUrl String?
38 | user User @relation(fields: [userId], references: [id])
39 | userId String
40 | like Int? @default(0)
41 | }
42 |
43 | model Resources {
44 | id Int @id @default(autoincrement())
45 | title String
46 | description String
47 | user User @relation(fields: [userId], references: [id])
48 | userId String
49 | categary String
50 | resourceLink String
51 | }
52 |
53 | model Account {
54 | userId String
55 | type String
56 | provider String
57 | providerAccountId String
58 | refresh_token String?
59 | access_token String?
60 | expires_at Int?
61 | token_type String?
62 | scope String?
63 | id_token String?
64 | session_state String?
65 |
66 | createdAt DateTime @default(now())
67 | updatedAt DateTime @updatedAt
68 |
69 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
70 |
71 | @@id([provider, providerAccountId])
72 | }
73 |
74 | model Session {
75 | sessionToken String @unique
76 | userId String
77 | expires DateTime
78 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
79 |
80 | createdAt DateTime @default(now())
81 | updatedAt DateTime @updatedAt
82 | }
83 |
84 | model VerificationToken {
85 | identifier String
86 | token String @unique
87 | expires DateTime
88 | email String?
89 |
90 | @@id([identifier, token])
91 | }
92 |
93 | // Optional for WebAuthn support
94 | model Authenticator {
95 | id String @id @default(cuid())
96 | credentialID String @unique
97 | userId String
98 | providerAccountId String
99 | credentialPublicKey String
100 | counter Int
101 | credentialDeviceType String
102 | credentialBackedUp Boolean
103 | transports String?
104 |
105 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
106 | }
107 |
--------------------------------------------------------------------------------
/app/resources/add/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { Button } from "@/components/ui/button";
4 | import { useState } from "react";
5 | import { useSession } from "next-auth/react";
6 | import { useRouter } from "next/navigation";
7 | import axios from "axios";
8 |
9 | export default function Add() {
10 | const [title, setTitle] = useState("");
11 | const [description, setDescription] = useState("");
12 | const [categary, setCategary] = useState("");
13 | const [resourceLink, setResourceLink] = useState("");
14 |
15 | const session = useSession();
16 | const router = useRouter();
17 |
18 | const handleOnClick = async () => {
19 | try {
20 | const apiUrl =
21 | process.env.NODE_ENV === "development"
22 | ? "http://localhost:3000/api/user/addresourse"
23 | : "https://www.unsight.club/api/user/addresourse";
24 | const res = await axios.post(apiUrl, {
25 | title: title,
26 | description: description,
27 | categary: categary,
28 | resourceLink: resourceLink,
29 | });
30 |
31 | router.push("/resources/all");
32 | return res.data;
33 | } catch (error) {
34 | console.log(error);
35 |
36 | return `Error: ${error}`;
37 | }
38 | };
39 |
40 | return (
41 |
42 |
43 |
44 | Add Resources
45 |
46 |
{
51 | setTitle(e.target.value);
52 | }}
53 | />
54 |
55 |
{
58 | setCategary(e.target.value);
59 | console.log(categary.toString());
60 | }}
61 | className="text-black border rounded-xl w-[80%] p-4 mb-2 shadow-md"
62 | >
63 | Select a categary
64 | Web Development
65 | AI and ML
66 | Blockchain & Web3
67 | DevOps
68 |
69 |
70 |
{
75 | setResourceLink(e.target.value);
76 | }}
77 | />
78 |
89 |
90 | Add
91 |
92 |
93 |
94 | );
95 | }
96 |
--------------------------------------------------------------------------------
/components/auth/signinWithEmail.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as z from "zod";
4 | import { useForm } from "react-hook-form";
5 | import { useState } from "react";
6 | import { zodResolver } from "@hookform/resolvers/zod";
7 | import {
8 | Form,
9 | FormControl,
10 | FormField,
11 | FormItem,
12 | FormLabel,
13 | FormMessage,
14 | } from "@/components/ui/form";
15 | import { Card, CardContent, CardHeader } from "@/components/ui/card";
16 | import { LoginSchema } from "@/schema";
17 | import { Input } from "@/components/ui/input";
18 | import { Button } from "@/components/ui/button";
19 | import { login } from "@/actions/login";
20 | import Link from "next/link";
21 | import SideSection from "./sideSection";
22 |
23 | export default function SignInForm() {
24 | const [success, setSuccess] = useState("");
25 |
26 | // Define your form
27 | const form = useForm>({
28 | resolver: zodResolver(LoginSchema),
29 | defaultValues: {
30 | email: "",
31 | },
32 | });
33 |
34 | const onSubmit = async (values: z.infer) => {
35 | login(values).then((data) => {
36 | if (data.success) {
37 | setSuccess(data.success);
38 | }
39 | });
40 | };
41 |
42 | return (
43 |
44 |
45 |
46 |
47 |
48 |
49 | Email Provider Authentication
50 |
51 |
52 |
53 |
87 |
88 |
89 |
90 | Create an account?
91 |
92 |
93 |
94 |
95 |
96 |
97 | );
98 | }
99 |
--------------------------------------------------------------------------------
/components/user/postPanel.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useRouter } from "next/navigation";
3 | import { Input } from "../ui/input";
4 | import { useState } from "react";
5 | import axios from "axios";
6 | import { throttle } from "./throttle";
7 |
8 | import { z } from "zod";
9 |
10 | export default function PostPanel() {
11 | const router = useRouter();
12 | const [description, setPost] = useState("");
13 | const [isAdding, setIsAdding] = useState(false);
14 |
15 | const handleOnclick = async () => {
16 | try {
17 | setIsAdding(true);
18 | const apiUrl =
19 | process.env.NODE_ENV === "development"
20 | ? "http://localhost:3000/api/user/createpost"
21 | : "https://www.unsight.club/api/user/createpost";
22 | const response = await axios.post(apiUrl, { description });
23 | setPost("");
24 | window.location.reload();
25 | return response.data;
26 | } finally {
27 | setIsAdding(false);
28 | }
29 | };
30 |
31 | const throttledAdd = throttle(handleOnclick, 2000);
32 |
33 | return (
34 |
35 | {/*
36 | Unsight - Anonymous and Professional Community of Students
37 | */}
38 |
39 |
{
41 | setPost(e.target.value);
42 | }}
43 | className="h-16 text-xl bg-black rounded-xl w-[100%]"
44 | placeholder="Start a post..."
45 | />
46 |
51 | {isAdding ? (
52 |
57 |
65 |
66 | ) : (
67 |
72 |
73 |
78 |
79 |
80 |
81 |
85 |
86 | )}
87 |
88 |
89 |
90 | );
91 | }
92 |
--------------------------------------------------------------------------------
/components/mainpage/intro.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from "../ui/card";
2 | import FeatureCard from "./featureCard";
3 |
4 | export default function IntroPage() {
5 | return (
6 |
7 |
8 | Verified Voices, Anonymous Conversations, Endless Insights.
9 |
10 |
11 |
15 |
19 |
20 | }
21 | description="Interact with the global student community, share your thoughts without hesitation"
22 | />
23 |
27 |
28 |
29 |
30 |
31 |
32 | }
33 | description="Help in peer learning by sharing resources & utilize huge number of resources tried by others "
34 | />
35 |
39 |
43 |
44 | }
45 | description="Anonymously share/see reviews"
46 | />
47 |
51 |
58 |
59 |
60 |
61 |
62 | }
63 | description="Build your network with other students around the world, share opportunities"
64 | />
65 |
66 |
67 | );
68 | }
69 |
--------------------------------------------------------------------------------
/components/auth/registerWithCred.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as z from "zod";
4 | import { useForm } from "react-hook-form";
5 | import { useState } from "react";
6 | import { zodResolver } from "@hookform/resolvers/zod";
7 | import Link from "next/link";
8 | import {
9 | Form,
10 | FormControl,
11 | FormField,
12 | FormItem,
13 | FormLabel,
14 | FormMessage,
15 | } from "@/components/ui/form";
16 | import { Card, CardContent, CardHeader } from "@/components/ui/card";
17 | import { RegisterSchema } from "@/schema";
18 | import { Input } from "@/components/ui/input";
19 | import { Button } from "@/components/ui/button";
20 | import { login } from "@/actions/login";
21 | import { register } from "@/actions/register";
22 | import SideSection from "./sideSection";
23 |
24 | const RegisterCredentialsForm = () => {
25 | const [success, setSuccess] = useState("");
26 |
27 | // Define your form
28 | const form = useForm>({
29 | resolver: zodResolver(RegisterSchema),
30 | defaultValues: {
31 | email: "",
32 | },
33 | });
34 |
35 | const onSubmit = async (values: z.infer) => {
36 | register(values).then((data) => {
37 | // setSuccess(data?.success);
38 | console.log(data);
39 | });
40 | };
41 |
42 | return (
43 |
44 |
45 |
46 |
47 |
48 | Register With Credentials
49 |
50 |
51 |
112 |
113 |
114 |
115 | Login
116 |
117 |
118 |
119 |
120 |
121 |
122 | );
123 | };
124 |
125 | export default RegisterCredentialsForm;
126 |
--------------------------------------------------------------------------------
/components/ui/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 |
--------------------------------------------------------------------------------
/components/ui/form.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as LabelPrimitive from "@radix-ui/react-label"
3 | import { Slot } from "@radix-ui/react-slot"
4 | import {
5 | Controller,
6 | ControllerProps,
7 | FieldPath,
8 | FieldValues,
9 | FormProvider,
10 | useFormContext,
11 | } from "react-hook-form"
12 |
13 | import { cn } from "@/lib/utils"
14 | import { Label } from "@/components/ui/label"
15 |
16 | const Form = FormProvider
17 |
18 | type FormFieldContextValue<
19 | TFieldValues extends FieldValues = FieldValues,
20 | TName extends FieldPath = FieldPath
21 | > = {
22 | name: TName
23 | }
24 |
25 | const FormFieldContext = React.createContext(
26 | {} as FormFieldContextValue
27 | )
28 |
29 | const FormField = <
30 | TFieldValues extends FieldValues = FieldValues,
31 | TName extends FieldPath = FieldPath
32 | >({
33 | ...props
34 | }: ControllerProps) => {
35 | return (
36 |
37 |
38 |
39 | )
40 | }
41 |
42 | const useFormField = () => {
43 | const fieldContext = React.useContext(FormFieldContext)
44 | const itemContext = React.useContext(FormItemContext)
45 | const { getFieldState, formState } = useFormContext()
46 |
47 | const fieldState = getFieldState(fieldContext.name, formState)
48 |
49 | if (!fieldContext) {
50 | throw new Error("useFormField should be used within ")
51 | }
52 |
53 | const { id } = itemContext
54 |
55 | return {
56 | id,
57 | name: fieldContext.name,
58 | formItemId: `${id}-form-item`,
59 | formDescriptionId: `${id}-form-item-description`,
60 | formMessageId: `${id}-form-item-message`,
61 | ...fieldState,
62 | }
63 | }
64 |
65 | type FormItemContextValue = {
66 | id: string
67 | }
68 |
69 | const FormItemContext = React.createContext(
70 | {} as FormItemContextValue
71 | )
72 |
73 | const FormItem = React.forwardRef<
74 | HTMLDivElement,
75 | React.HTMLAttributes
76 | >(({ className, ...props }, ref) => {
77 | const id = React.useId()
78 |
79 | return (
80 |
81 |
82 |
83 | )
84 | })
85 | FormItem.displayName = "FormItem"
86 |
87 | const FormLabel = React.forwardRef<
88 | React.ElementRef,
89 | React.ComponentPropsWithoutRef
90 | >(({ className, ...props }, ref) => {
91 | const { error, formItemId } = useFormField()
92 |
93 | return (
94 |
100 | )
101 | })
102 | FormLabel.displayName = "FormLabel"
103 |
104 | const FormControl = React.forwardRef<
105 | React.ElementRef,
106 | React.ComponentPropsWithoutRef
107 | >(({ ...props }, ref) => {
108 | const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
109 |
110 | return (
111 |
122 | )
123 | })
124 | FormControl.displayName = "FormControl"
125 |
126 | const FormDescription = React.forwardRef<
127 | HTMLParagraphElement,
128 | React.HTMLAttributes
129 | >(({ className, ...props }, ref) => {
130 | const { formDescriptionId } = useFormField()
131 |
132 | return (
133 |
139 | )
140 | })
141 | FormDescription.displayName = "FormDescription"
142 |
143 | const FormMessage = React.forwardRef<
144 | HTMLParagraphElement,
145 | React.HTMLAttributes
146 | >(({ className, children, ...props }, ref) => {
147 | const { error, formMessageId } = useFormField()
148 | const body = error ? String(error?.message) : children
149 |
150 | if (!body) {
151 | return null
152 | }
153 |
154 | return (
155 |
161 | {body}
162 |
163 | )
164 | })
165 | FormMessage.displayName = "FormMessage"
166 |
167 | export {
168 | useFormField,
169 | Form,
170 | FormItem,
171 | FormLabel,
172 | FormControl,
173 | FormDescription,
174 | FormMessage,
175 | FormField,
176 | }
177 |
--------------------------------------------------------------------------------
/app/dashboard/feed/posts.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { Card } from "@/components/ui/card";
4 | import axios from "axios";
5 | import { useEffect, useState } from "react";
6 |
7 | export function Posts({
8 | id,
9 | description,
10 | imgUrl,
11 | likes,
12 | userId,
13 | }: {
14 | id: number;
15 | description: string;
16 | imgUrl: string | null;
17 | likes: number | null;
18 | userId: string;
19 | }) {
20 | const [isLiked, setIsLiked] = useState(false);
21 |
22 | const handleLike = async () => {
23 | try {
24 | const apiUrl =
25 | process.env.NODE_ENV === "development"
26 | ? "http://localhost:3000/api/user/likepost"
27 | : "https://www.unsight.club/api/user/likepost";
28 | const res = await axios.post(apiUrl, {
29 | postId: id,
30 | });
31 |
32 | window.location.reload();
33 | return res.data;
34 | } catch (error) {
35 | return error;
36 | }
37 | };
38 |
39 | return (
40 |
41 |
42 |
51 |
52 |
{userId}
53 |
ex-SpaceX
54 |
55 |
56 |
57 | {description}
58 |
59 |
63 |
68 |
69 |
73 |
74 |
75 |
76 |
{likes ? likes : 0}
77 |
78 |
79 |
80 |
85 |
86 |
87 |
91 |
92 |
93 |
{likes ? likes : 0}
94 |
95 |
96 |
97 |
102 |
103 |
108 |
115 |
116 |
117 |
{likes ? likes : 1}
118 |
119 |
120 |
121 | );
122 | }
123 |
--------------------------------------------------------------------------------
/components/mainpage/mainpage.tsx:
--------------------------------------------------------------------------------
1 | import MainpageTitle from "./mainpagetitle";
2 | import Reveal from "../reveal";
3 | import Penn from "@/public/Penn.png";
4 | import MIT from "@/public/MIT.png";
5 | import Cambridge from "@/public/Cambridge.png";
6 | import Oxford from "@/public/Oxford.png";
7 | import Nasa from "@/public/NASA.png";
8 | import Image from "next/image";
9 | import un from "@/public/un.png";
10 | import unsightcover from "@/public/unsightcover.png";
11 | import IntroPage from "./intro";
12 | import ImageBanner from "./imagebanner";
13 | import Footer from "./footer";
14 | export default function Mainpage() {
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |
28 |
29 |
30 |
31 |
32 |
33 | Featured on
34 |
35 |
36 |
41 |
45 |
46 |
Hacker News
47 |
48 |
49 |
50 |
55 |
62 |
63 |
64 |
65 |
66 |
Product Hunt
67 |
68 |
80 |
81 |
86 |
91 |
92 |
Reddit
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | );
108 | }
109 |
--------------------------------------------------------------------------------
/components/ui/toast.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ToastPrimitives from "@radix-ui/react-toast"
5 | import { cva, type VariantProps } from "class-variance-authority"
6 | import { X } from "lucide-react"
7 |
8 | import { cn } from "@/lib/utils"
9 |
10 | const ToastProvider = ToastPrimitives.Provider
11 |
12 | const ToastViewport = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, ...props }, ref) => (
16 |
24 | ))
25 | ToastViewport.displayName = ToastPrimitives.Viewport.displayName
26 |
27 | const toastVariants = cva(
28 | "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
29 | {
30 | variants: {
31 | variant: {
32 | default: "border bg-background text-foreground",
33 | destructive:
34 | "destructive group border-destructive bg-destructive text-destructive-foreground",
35 | },
36 | },
37 | defaultVariants: {
38 | variant: "default",
39 | },
40 | }
41 | )
42 |
43 | const Toast = React.forwardRef<
44 | React.ElementRef,
45 | React.ComponentPropsWithoutRef &
46 | VariantProps
47 | >(({ className, variant, ...props }, ref) => {
48 | return (
49 |
54 | )
55 | })
56 | Toast.displayName = ToastPrimitives.Root.displayName
57 |
58 | const ToastAction = React.forwardRef<
59 | React.ElementRef,
60 | React.ComponentPropsWithoutRef
61 | >(({ className, ...props }, ref) => (
62 |
70 | ))
71 | ToastAction.displayName = ToastPrimitives.Action.displayName
72 |
73 | const ToastClose = React.forwardRef<
74 | React.ElementRef,
75 | React.ComponentPropsWithoutRef
76 | >(({ className, ...props }, ref) => (
77 |
86 |
87 |
88 | ))
89 | ToastClose.displayName = ToastPrimitives.Close.displayName
90 |
91 | const ToastTitle = React.forwardRef<
92 | React.ElementRef,
93 | React.ComponentPropsWithoutRef
94 | >(({ className, ...props }, ref) => (
95 |
100 | ))
101 | ToastTitle.displayName = ToastPrimitives.Title.displayName
102 |
103 | const ToastDescription = React.forwardRef<
104 | React.ElementRef,
105 | React.ComponentPropsWithoutRef
106 | >(({ className, ...props }, ref) => (
107 |
112 | ))
113 | ToastDescription.displayName = ToastPrimitives.Description.displayName
114 |
115 | type ToastProps = React.ComponentPropsWithoutRef
116 |
117 | type ToastActionElement = React.ReactElement
118 |
119 | export {
120 | type ToastProps,
121 | type ToastActionElement,
122 | ToastProvider,
123 | ToastViewport,
124 | Toast,
125 | ToastTitle,
126 | ToastDescription,
127 | ToastClose,
128 | ToastAction,
129 | }
130 |
--------------------------------------------------------------------------------
/components/mainpage/footer.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "../ui/button";
2 | import Link from "next/link";
3 |
4 | export default function Footer() {
5 | return (
6 |
7 |
8 |
9 |
Join Unsight Community!
10 |
11 | Join a simple initiative to connect students all across the globe,
12 |
13 |
14 | {" "}
15 | indulge with them, share your thoughts & network.
16 |
17 |
18 |
19 | Sign in using student email
20 |
21 |
22 |
23 |
24 |
25 |
26 |
33 |
37 |
38 |
39 | 2024 Unsight, Inc
40 |
41 |
42 | Terms
43 |
44 |
45 | Privacy
46 |
47 |
48 | Sitemap
49 |
50 |
51 |
101 |
102 |
103 | );
104 | }
105 |
--------------------------------------------------------------------------------
/components/navbar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { Input } from "./ui/input";
3 | import { Button } from "./ui/button";
4 | import Link from "next/link";
5 | import { useSession } from "next-auth/react";
6 | import { signOut } from "next-auth/react";
7 | import { usePathname } from "next/navigation";
8 |
9 | const IS_ACTIVE =
10 | "mx-6 flex flex-col items-center border-b-4 border-slate-300 hover:scale-110 transition-all duration-300 ";
11 | const INACTIVE =
12 | "mx-6 flex flex-col items-center hover:scale-110 transition-all duration-300";
13 |
14 | export default function Navbar() {
15 | const session = useSession();
16 | const pathname = usePathname();
17 | return (
18 |
19 |
20 |
21 |
26 |
27 | {/*
*/}
31 |
32 | unsight
33 |
34 |
35 |
36 |
37 |
38 |
39 |
42 |
47 | Home
48 |
49 |
50 |
51 |
54 |
59 | Resources
60 |
61 |
62 |
63 |
64 |
69 | Reviews
70 |
71 |
72 |
73 |
76 |
81 | Opportunities
82 |
83 |
84 |
85 |
86 |
87 |
88 | {session.data ? (
89 |
90 |
91 |
92 | dashboard
93 |
94 |
95 | {
97 | signOut();
98 | }}
99 | className="hover:bg-[#4477ed] hover:text-black bg-[#023262] transition-all duration-300 mx-2"
100 | >
101 | logout
102 |
103 |
104 | ) : (
105 |
106 |
107 |
108 | Sign in
109 |
110 |
111 |
112 |
113 | Register
114 |
115 |
116 |
117 | )}
118 |
119 |
120 | );
121 | }
122 |
--------------------------------------------------------------------------------
/components/sidebar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import Link from "next/link";
4 | import { usePathname } from "next/navigation";
5 |
6 | const ACTIVE =
7 | "h-12 font-bold my-1 bg-slate-400 rounded-lg p-2 flex items-center";
8 | const INACTIVE =
9 | "h-12 font-bold my-1 bg-black text-white rounded-lg p-2 flex items-center hover:bg-slate-600 transition-all duration-300";
10 |
11 | export default function Sidebar() {
12 | const pathname = usePathname();
13 | return (
14 |
15 |
16 | {pathname === "/dashboard/feed" ? (
17 |
18 |
23 |
Feed
24 |
25 | ) : (
26 |
27 |
28 |
33 |
Feed
34 |
35 |
36 | )}
37 |
38 | {pathname === "/dashboard/bookmarks" ? (
39 |
40 |
45 |
Bookmarks
46 |
47 | ) : (
48 |
49 |
50 |
55 |
Bookmarks
56 |
57 |
58 | )}
59 | {pathname === "/dashboard/explore" ? (
60 |
61 |
66 |
Explore
67 |
68 | ) : (
69 |
70 |
71 |
76 |
Explore
77 |
78 |
79 | )}
80 | {pathname === "/dashboard/profile" ? (
81 |
82 |
87 |
Profile
88 |
89 | ) : (
90 |
91 |
92 |
97 |
Profile
98 |
99 |
100 | )}
101 |
102 |
103 |
INDUSTRIES
104 |
105 | Tech
106 | Healthcare
107 | Financial Services
108 |
109 |
110 |
Show more
111 |
116 |
117 |
118 |
122 |
123 |
124 |
125 |
126 |
127 | );
128 | }
129 |
--------------------------------------------------------------------------------
/app/resources/sidepanel.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { Button } from "@react-email/components";
4 | import Link from "next/link";
5 | import { usePathname } from "next/navigation";
6 |
7 | const ACTIVE =
8 | "h-12 font-bold my-1 bg-slate-400 rounded-lg p-2 flex items-center";
9 | const INACTIVE =
10 | "h-12 font-bold my-1 bg-black text-white rounded-lg p-2 flex items-center hover:bg-slate-600 transition-all duration-300";
11 |
12 | export default function SidePanel() {
13 | const pathname = usePathname();
14 | return (
15 |
16 |
17 | {pathname === "/resources/all" ? (
18 |
19 |
24 |
All
25 |
26 | ) : (
27 |
28 |
29 |
34 |
All
35 |
36 |
37 | )}
38 |
39 | {pathname === "/resources/webdev" ? (
40 |
41 |
46 |
webdev
47 |
48 | ) : (
49 |
50 |
51 |
56 |
webdev
57 |
58 |
59 | )}
60 | {pathname === "/resources/blockchain" ? (
61 |
62 |
67 |
Blockchain
68 |
69 | ) : (
70 |
71 |
72 |
77 |
Blockchain
78 |
79 |
80 | )}
81 | {pathname === "/resources/aiml" ? (
82 |
83 |
88 |
AI and ML
89 |
90 | ) : (
91 |
92 |
93 |
98 |
AI and ML
99 |
100 |
101 | )}
102 | {pathname === "/resources/devops" ? (
103 |
104 |
109 |
Devops
110 |
111 | ) : (
112 |
113 |
114 |
119 |
Devops
120 |
121 |
122 | )}
123 |
124 |
125 |
126 | Add Resources
127 |
128 |
129 |
130 | );
131 | }
132 |
--------------------------------------------------------------------------------