87 | >(({ className, ...props }, ref) => (
88 | [role=checkbox]]:translate-y-[2px]",
92 | className
93 | )}
94 | {...props}
95 | />
96 | ))
97 | TableCell.displayName = "TableCell"
98 |
99 | const TableCaption = React.forwardRef<
100 | HTMLTableCaptionElement,
101 | React.HTMLAttributes
102 | >(({ className, ...props }, ref) => (
103 |
108 | ))
109 | TableCaption.displayName = "TableCaption"
110 |
111 | export {
112 | Table,
113 | TableHeader,
114 | TableBody,
115 | TableFooter,
116 | TableHead,
117 | TableRow,
118 | TableCell,
119 | TableCaption,
120 | }
121 |
--------------------------------------------------------------------------------
/components/ui/tabs.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as TabsPrimitive from "@radix-ui/react-tabs"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Tabs = TabsPrimitive.Root
9 |
10 | const TabsList = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, ...props }, ref) => (
14 |
22 | ))
23 | TabsList.displayName = TabsPrimitive.List.displayName
24 |
25 | const TabsTrigger = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, ...props }, ref) => (
29 |
37 | ))
38 | TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
39 |
40 | const TabsContent = React.forwardRef<
41 | React.ElementRef,
42 | React.ComponentPropsWithoutRef
43 | >(({ className, ...props }, ref) => (
44 |
52 | ))
53 | TabsContent.displayName = TabsPrimitive.Content.displayName
54 |
55 | export { Tabs, TabsList, TabsTrigger, TabsContent }
56 |
--------------------------------------------------------------------------------
/components/ui/textarea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | export interface TextareaProps
6 | extends React.TextareaHTMLAttributes {}
7 |
8 | const Textarea = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | )
20 | }
21 | )
22 | Textarea.displayName = "Textarea"
23 |
24 | export { Textarea }
25 |
--------------------------------------------------------------------------------
/components/ui/tooltip.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as TooltipPrimitive from "@radix-ui/react-tooltip"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const TooltipProvider = TooltipPrimitive.Provider
9 |
10 | const Tooltip = TooltipPrimitive.Root
11 |
12 | const TooltipTrigger = TooltipPrimitive.Trigger
13 |
14 | const TooltipContent = React.forwardRef<
15 | React.ElementRef,
16 | React.ComponentPropsWithoutRef
17 | >(({ className, sideOffset = 4, ...props }, ref) => (
18 |
27 | ))
28 | TooltipContent.displayName = TooltipPrimitive.Content.displayName
29 |
30 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
31 |
--------------------------------------------------------------------------------
/env.example:
--------------------------------------------------------------------------------
1 | NEXTAUTH_SECRET=
2 | DATABASE_URL=
3 | GOOGLE_CLIENT_ID=
4 | GOOGLE_CLIENT_SECRET=
5 | AUTH_TRUST_HOST=
--------------------------------------------------------------------------------
/lib/auth.ts:
--------------------------------------------------------------------------------
1 | import NextAuth from "next-auth";
2 | import { PrismaAdapter } from "@auth/prisma-adapter";
3 | import Google from "next-auth/providers/google";
4 | import prisma from "./db";
5 |
6 | export const { handlers, auth, signIn, signOut } = NextAuth({
7 | adapter: PrismaAdapter(prisma),
8 | providers: [
9 | Google({
10 | clientId: process.env.GOOGLE_CLIENT_ID,
11 | clientSecret: process.env.GOOGLE_CLIENT_SECRET,
12 | }),
13 | ],
14 | pages: {
15 | error: "/",
16 | signIn: "/",
17 | signOut: "/",
18 | },
19 | session: {
20 | strategy: "jwt",
21 | },
22 | trustHost: true,
23 | secret: process.env.NEXTAUTH_SECRET!,
24 | });
25 |
--------------------------------------------------------------------------------
/lib/db.ts:
--------------------------------------------------------------------------------
1 | import { PrismaClient } from "@prisma/client";
2 |
3 | const prismaClientSingleton = () => {
4 | return new PrismaClient();
5 | };
6 |
7 | declare const globalThis: {
8 | prismaGlobal: ReturnType;
9 | } & typeof global;
10 |
11 | const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();
12 |
13 | export default prisma;
14 |
15 | if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma;
16 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | images: {
4 | remotePatterns: [
5 | {
6 | protocol: "https",
7 | hostname: "utfs.io",
8 | },
9 | {
10 | protocol: "https",
11 | hostname: "res.cloudinary.com",
12 | },
13 | {
14 | protocol: "https",
15 | hostname: "cdn.freelogovectors.net",
16 | },
17 | ],
18 |
19 | },
20 | async headers() {
21 | return [
22 | {
23 | // matching all API routes
24 | source: "/api/:path*",
25 | headers: [
26 | { key: "Access-Control-Allow-Credentials", value: "true" },
27 | { key: "Access-Control-Allow-Origin", value: "*" },
28 | {
29 | key: "Access-Control-Allow-Methods",
30 | value: "POST",
31 | },
32 | {
33 | key: "Access-Control-Allow-Headers",
34 | value:
35 | "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
36 | },
37 | ],
38 | },
39 | ];
40 | },
41 | compiler: {
42 | removeConsole: process.env.AUTH_TRUST_HOST !== "http://localhost:3000" // Remove console.log in production
43 | }
44 | };
45 |
46 | export default nextConfig;
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "opinify",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint",
10 | "postinstall": "prisma generate"
11 | },
12 | "dependencies": {
13 | "@auth/prisma-adapter": "^2.4.2",
14 | "@prisma/client": "^5.17.0",
15 | "@radix-ui/react-accordion": "^1.2.0",
16 | "@radix-ui/react-avatar": "^1.1.0",
17 | "@radix-ui/react-dialog": "^1.1.1",
18 | "@radix-ui/react-dropdown-menu": "^2.1.1",
19 | "@radix-ui/react-icons": "^1.3.0",
20 | "@radix-ui/react-label": "^2.1.0",
21 | "@radix-ui/react-progress": "^1.1.0",
22 | "@radix-ui/react-select": "^2.1.1",
23 | "@radix-ui/react-separator": "^1.1.0",
24 | "@radix-ui/react-slot": "^1.1.0",
25 | "@radix-ui/react-tabs": "^1.1.0",
26 | "@radix-ui/react-tooltip": "^1.1.2",
27 | "@types/papaparse": "^5.3.14",
28 | "@types/react-syntax-highlighter": "^15.5.13",
29 | "@vercel/analytics": "^1.3.1",
30 | "@vercel/speed-insights": "^1.0.12",
31 | "class-variance-authority": "^0.7.0",
32 | "clsx": "^2.1.1",
33 | "framer-motion": "^11.9.0",
34 | "lucide-react": "^0.424.0",
35 | "next": "14.2.5",
36 | "next-auth": "^5.0.0-beta.20",
37 | "next-themes": "^0.3.0",
38 | "nextjs-toploader": "^1.6.12",
39 | "papaparse": "^5.4.1",
40 | "prisma": "^5.17.0",
41 | "react": "^18.3.1",
42 | "react-dom": "^18",
43 | "react-markdown": "^9.0.1",
44 | "react-syntax-highlighter": "^15.5.0",
45 | "sonner": "^1.5.0",
46 | "tailwind-merge": "^2.4.0",
47 | "tailwindcss-animate": "^1.0.7",
48 | "zod": "^3.23.8"
49 | },
50 | "devDependencies": {
51 | "@types/node": "^20",
52 | "@types/react": "^18",
53 | "@types/react-dom": "^18",
54 | "eslint": "^8",
55 | "eslint-config-next": "14.2.5",
56 | "postcss": "^8",
57 | "tailwindcss": "^3.4.1",
58 | "typescript": "^5"
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('postcss-load-config').Config} */
2 | const config = {
3 | plugins: {
4 | tailwindcss: {},
5 | },
6 | };
7 |
8 | export default config;
9 |
--------------------------------------------------------------------------------
/prisma/migrations/20240806032711_initial_migration_for_authentication/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 |
48 | CONSTRAINT "VerificationToken_pkey" PRIMARY KEY ("identifier","token")
49 | );
50 |
51 | -- CreateTable
52 | CREATE TABLE "Authenticator" (
53 | "credentialID" TEXT NOT NULL,
54 | "userId" TEXT NOT NULL,
55 | "providerAccountId" TEXT NOT NULL,
56 | "credentialPublicKey" TEXT NOT NULL,
57 | "counter" INTEGER NOT NULL,
58 | "credentialDeviceType" TEXT NOT NULL,
59 | "credentialBackedUp" BOOLEAN NOT NULL,
60 | "transports" TEXT,
61 |
62 | CONSTRAINT "Authenticator_pkey" PRIMARY KEY ("userId","credentialID")
63 | );
64 |
65 | -- CreateIndex
66 | CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
67 |
68 | -- CreateIndex
69 | CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken");
70 |
71 | -- CreateIndex
72 | CREATE UNIQUE INDEX "Authenticator_credentialID_key" ON "Authenticator"("credentialID");
73 |
74 | -- AddForeignKey
75 | ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
76 |
77 | -- AddForeignKey
78 | ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
79 |
80 | -- AddForeignKey
81 | ALTER TABLE "Authenticator" ADD CONSTRAINT "Authenticator_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
82 |
--------------------------------------------------------------------------------
/prisma/migrations/20240806042013_corrected_auth_table/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the `Account` table. If the table is not empty, all the data it contains will be lost.
5 | - You are about to drop the `Authenticator` table. If the table is not empty, all the data it contains will be lost.
6 | - You are about to drop the `Session` table. If the table is not empty, all the data it contains will be lost.
7 | - You are about to drop the `User` table. If the table is not empty, all the data it contains will be lost.
8 | - You are about to drop the `VerificationToken` table. If the table is not empty, all the data it contains will be lost.
9 |
10 | */
11 | -- DropForeignKey
12 | ALTER TABLE "Account" DROP CONSTRAINT "Account_userId_fkey";
13 |
14 | -- DropForeignKey
15 | ALTER TABLE "Authenticator" DROP CONSTRAINT "Authenticator_userId_fkey";
16 |
17 | -- DropForeignKey
18 | ALTER TABLE "Session" DROP CONSTRAINT "Session_userId_fkey";
19 |
20 | -- DropTable
21 | DROP TABLE "Account";
22 |
23 | -- DropTable
24 | DROP TABLE "Authenticator";
25 |
26 | -- DropTable
27 | DROP TABLE "Session";
28 |
29 | -- DropTable
30 | DROP TABLE "User";
31 |
32 | -- DropTable
33 | DROP TABLE "VerificationToken";
34 |
35 | -- CreateTable
36 | CREATE TABLE "accounts" (
37 | "id" TEXT NOT NULL,
38 | "user_id" TEXT NOT NULL,
39 | "type" TEXT NOT NULL,
40 | "provider" TEXT NOT NULL,
41 | "provider_account_id" TEXT NOT NULL,
42 | "refresh_token" TEXT,
43 | "access_token" TEXT,
44 | "expires_at" INTEGER,
45 | "token_type" TEXT,
46 | "scope" TEXT,
47 | "id_token" TEXT,
48 | "session_state" TEXT,
49 |
50 | CONSTRAINT "accounts_pkey" PRIMARY KEY ("id")
51 | );
52 |
53 | -- CreateTable
54 | CREATE TABLE "sessions" (
55 | "id" TEXT NOT NULL,
56 | "session_token" TEXT NOT NULL,
57 | "user_id" TEXT NOT NULL,
58 | "expires" TIMESTAMP(3) NOT NULL,
59 |
60 | CONSTRAINT "sessions_pkey" PRIMARY KEY ("id")
61 | );
62 |
63 | -- CreateTable
64 | CREATE TABLE "users" (
65 | "id" TEXT NOT NULL,
66 | "name" TEXT,
67 | "email" TEXT,
68 | "email_verified" TIMESTAMP(3),
69 | "image" TEXT,
70 |
71 | CONSTRAINT "users_pkey" PRIMARY KEY ("id")
72 | );
73 |
74 | -- CreateTable
75 | CREATE TABLE "verificationtokens" (
76 | "identifier" TEXT NOT NULL,
77 | "token" TEXT NOT NULL,
78 | "expires" TIMESTAMP(3) NOT NULL
79 | );
80 |
81 | -- CreateIndex
82 | CREATE UNIQUE INDEX "accounts_provider_provider_account_id_key" ON "accounts"("provider", "provider_account_id");
83 |
84 | -- CreateIndex
85 | CREATE UNIQUE INDEX "sessions_session_token_key" ON "sessions"("session_token");
86 |
87 | -- CreateIndex
88 | CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
89 |
90 | -- CreateIndex
91 | CREATE UNIQUE INDEX "verificationtokens_identifier_token_key" ON "verificationtokens"("identifier", "token");
92 |
93 | -- AddForeignKey
94 | ALTER TABLE "accounts" ADD CONSTRAINT "accounts_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
95 |
96 | -- AddForeignKey
97 | ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
98 |
--------------------------------------------------------------------------------
/prisma/migrations/20240806174843_added_project_schema/migration.sql:
--------------------------------------------------------------------------------
1 | -- CreateTable
2 | CREATE TABLE "Project" (
3 | "id" TEXT NOT NULL,
4 | "name" TEXT NOT NULL,
5 | "url" TEXT NOT NULL,
6 | "description" TEXT NOT NULL,
7 | "userId" TEXT NOT NULL,
8 |
9 | CONSTRAINT "Project_pkey" PRIMARY KEY ("id")
10 | );
11 |
12 | -- AddForeignKey
13 | ALTER TABLE "Project" ADD CONSTRAINT "Project_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
14 |
--------------------------------------------------------------------------------
/prisma/migrations/20240807043409_added_schema_for_the_feedbacks_and_updated_at_constraints/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - A unique constraint covering the columns `[url]` on the table `Project` will be added. If there are existing duplicate values, this will fail.
5 | - Added the required column `updatedAt` to the `Project` table without a default value. This is not possible if the table is not empty.
6 |
7 | */
8 | -- AlterTable
9 | ALTER TABLE "Project" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
10 | ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL;
11 |
12 | -- CreateTable
13 | CREATE TABLE "feedbacks" (
14 | "id" TEXT NOT NULL,
15 | "project_id" TEXT NOT NULL,
16 | "feedback" TEXT NOT NULL,
17 | "rating" INTEGER NOT NULL DEFAULT 3,
18 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
19 | "updatedAt" TIMESTAMP(3) NOT NULL,
20 |
21 | CONSTRAINT "feedbacks_pkey" PRIMARY KEY ("id")
22 | );
23 |
24 | -- CreateIndex
25 | CREATE UNIQUE INDEX "Project_url_key" ON "Project"("url");
26 |
27 | -- AddForeignKey
28 | ALTER TABLE "feedbacks" ADD CONSTRAINT "feedbacks_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
29 |
--------------------------------------------------------------------------------
/prisma/migrations/20240807103708_fixed_the_feedback_schema/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `updatedAt` on the `Project` table. All the data in the column will be lost.
5 | - You are about to drop the column `project_id` on the `feedbacks` table. All the data in the column will be lost.
6 | - You are about to drop the column `updatedAt` on the `feedbacks` table. All the data in the column will be lost.
7 | - Added the required column `email` to the `feedbacks` table without a default value. This is not possible if the table is not empty.
8 | - Added the required column `name` to the `feedbacks` table without a default value. This is not possible if the table is not empty.
9 | - Added the required column `projectId` to the `feedbacks` table without a default value. This is not possible if the table is not empty.
10 |
11 | */
12 | -- DropForeignKey
13 | ALTER TABLE "feedbacks" DROP CONSTRAINT "feedbacks_project_id_fkey";
14 |
15 | -- AlterTable
16 | ALTER TABLE "Project" DROP COLUMN "updatedAt";
17 |
18 | -- AlterTable
19 | ALTER TABLE "feedbacks" DROP COLUMN "project_id",
20 | DROP COLUMN "updatedAt",
21 | ADD COLUMN "email" TEXT NOT NULL,
22 | ADD COLUMN "name" TEXT NOT NULL,
23 | ADD COLUMN "projectId" TEXT NOT NULL;
24 |
25 | -- AddForeignKey
26 | ALTER TABLE "feedbacks" ADD CONSTRAINT "feedbacks_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
27 |
--------------------------------------------------------------------------------
/prisma/migrations/20240807105030_refactored_whole_schema/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `access_token` on the `accounts` table. All the data in the column will be lost.
5 | - You are about to drop the column `expires_at` on the `accounts` table. All the data in the column will be lost.
6 | - You are about to drop the column `id_token` on the `accounts` table. All the data in the column will be lost.
7 | - You are about to drop the column `refresh_token` on the `accounts` table. All the data in the column will be lost.
8 | - You are about to drop the column `session_state` on the `accounts` table. All the data in the column will be lost.
9 | - You are about to drop the column `token_type` on the `accounts` table. All the data in the column will be lost.
10 | - You are about to drop the `Project` table. If the table is not empty, all the data it contains will be lost.
11 |
12 | */
13 | -- DropForeignKey
14 | ALTER TABLE "Project" DROP CONSTRAINT "Project_userId_fkey";
15 |
16 | -- DropForeignKey
17 | ALTER TABLE "feedbacks" DROP CONSTRAINT "feedbacks_projectId_fkey";
18 |
19 | -- AlterTable
20 | ALTER TABLE "accounts" DROP COLUMN "access_token",
21 | DROP COLUMN "expires_at",
22 | DROP COLUMN "id_token",
23 | DROP COLUMN "refresh_token",
24 | DROP COLUMN "session_state",
25 | DROP COLUMN "token_type",
26 | ADD COLUMN "accessToken" TEXT,
27 | ADD COLUMN "expiresAt" INTEGER,
28 | ADD COLUMN "idToken" TEXT,
29 | ADD COLUMN "refreshToken" TEXT,
30 | ADD COLUMN "sessionState" TEXT,
31 | ADD COLUMN "tokenType" TEXT;
32 |
33 | -- DropTable
34 | DROP TABLE "Project";
35 |
36 | -- CreateTable
37 | CREATE TABLE "projects" (
38 | "id" TEXT NOT NULL,
39 | "name" TEXT NOT NULL,
40 | "url" TEXT NOT NULL,
41 | "description" TEXT NOT NULL,
42 | "userId" TEXT NOT NULL,
43 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
44 |
45 | CONSTRAINT "projects_pkey" PRIMARY KEY ("id")
46 | );
47 |
48 | -- CreateIndex
49 | CREATE UNIQUE INDEX "projects_url_key" ON "projects"("url");
50 |
51 | -- AddForeignKey
52 | ALTER TABLE "projects" ADD CONSTRAINT "projects_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
53 |
54 | -- AddForeignKey
55 | ALTER TABLE "feedbacks" ADD CONSTRAINT "feedbacks_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
56 |
--------------------------------------------------------------------------------
/prisma/migrations/20240807180653_added_foreign_key_in_feedback_model/migration.sql:
--------------------------------------------------------------------------------
1 | -- DropForeignKey
2 | ALTER TABLE "feedbacks" DROP CONSTRAINT "feedbacks_projectId_fkey";
3 |
4 | -- AddForeignKey
5 | ALTER TABLE "feedbacks" ADD CONSTRAINT "feedbacks_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
6 |
--------------------------------------------------------------------------------
/prisma/migrations/20240807181025_refatored/migration.sql:
--------------------------------------------------------------------------------
1 | -- DropForeignKey
2 | ALTER TABLE "feedbacks" DROP CONSTRAINT "feedbacks_projectId_fkey";
3 |
4 | -- AddForeignKey
5 | ALTER TABLE "feedbacks" ADD CONSTRAINT "feedbacks_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
6 |
--------------------------------------------------------------------------------
/prisma/migrations/20240807181559_refactored/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - You are about to drop the column `email_verified` on the `users` table. All the data in the column will be lost.
5 | - You are about to drop the `accounts` table. If the table is not empty, all the data it contains will be lost.
6 | - You are about to drop the `sessions` table. If the table is not empty, all the data it contains will be lost.
7 | - You are about to drop the `verificationtokens` table. If the table is not empty, all the data it contains will be lost.
8 | - Added the required column `updatedAt` to the `users` table without a default value. This is not possible if the table is not empty.
9 | - Made the column `email` on table `users` required. This step will fail if there are existing NULL values in that column.
10 |
11 | */
12 | -- DropForeignKey
13 | ALTER TABLE "accounts" DROP CONSTRAINT "accounts_user_id_fkey";
14 |
15 | -- DropForeignKey
16 | ALTER TABLE "sessions" DROP CONSTRAINT "sessions_user_id_fkey";
17 |
18 | -- AlterTable
19 | ALTER TABLE "users" DROP COLUMN "email_verified",
20 | ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
21 | ADD COLUMN "emailVerified" TIMESTAMP(3),
22 | ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL,
23 | ALTER COLUMN "email" SET NOT NULL;
24 |
25 | -- DropTable
26 | DROP TABLE "accounts";
27 |
28 | -- DropTable
29 | DROP TABLE "sessions";
30 |
31 | -- DropTable
32 | DROP TABLE "verificationtokens";
33 |
34 | -- CreateTable
35 | CREATE TABLE "Authenticator" (
36 | "credentialID" TEXT NOT NULL,
37 | "userId" TEXT NOT NULL,
38 | "providerAccountId" TEXT NOT NULL,
39 | "credentialPublicKey" TEXT NOT NULL,
40 | "counter" INTEGER NOT NULL,
41 | "credentialDeviceType" TEXT NOT NULL,
42 | "credentialBackedUp" BOOLEAN NOT NULL,
43 | "transports" TEXT,
44 |
45 | CONSTRAINT "Authenticator_pkey" PRIMARY KEY ("userId","credentialID")
46 | );
47 |
48 | -- CreateTable
49 | CREATE TABLE "Account" (
50 | "userId" TEXT NOT NULL,
51 | "type" TEXT NOT NULL,
52 | "provider" TEXT NOT NULL,
53 | "providerAccountId" TEXT NOT NULL,
54 | "refresh_token" TEXT,
55 | "access_token" TEXT,
56 | "expires_at" INTEGER,
57 | "token_type" TEXT,
58 | "scope" TEXT,
59 | "id_token" TEXT,
60 | "session_state" TEXT,
61 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
62 | "updatedAt" TIMESTAMP(3) NOT NULL,
63 |
64 | CONSTRAINT "Account_pkey" PRIMARY KEY ("provider","providerAccountId")
65 | );
66 |
67 | -- CreateTable
68 | CREATE TABLE "Session" (
69 | "sessionToken" TEXT NOT NULL,
70 | "userId" TEXT NOT NULL,
71 | "expires" TIMESTAMP(3) NOT NULL,
72 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
73 | "updatedAt" TIMESTAMP(3) NOT NULL
74 | );
75 |
76 | -- CreateTable
77 | CREATE TABLE "VerificationToken" (
78 | "identifier" TEXT NOT NULL,
79 | "token" TEXT NOT NULL,
80 | "expires" TIMESTAMP(3) NOT NULL,
81 |
82 | CONSTRAINT "VerificationToken_pkey" PRIMARY KEY ("identifier","token")
83 | );
84 |
85 | -- CreateIndex
86 | CREATE UNIQUE INDEX "Authenticator_credentialID_key" ON "Authenticator"("credentialID");
87 |
88 | -- CreateIndex
89 | CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken");
90 |
91 | -- AddForeignKey
92 | ALTER TABLE "Authenticator" ADD CONSTRAINT "Authenticator_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
93 |
94 | -- AddForeignKey
95 | ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
96 |
97 | -- AddForeignKey
98 | ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
99 |
--------------------------------------------------------------------------------
/prisma/migrations/20240809085715_adding/migration.sql:
--------------------------------------------------------------------------------
1 | -- DropForeignKey
2 | ALTER TABLE "feedbacks" DROP CONSTRAINT "feedbacks_projectId_fkey";
3 |
4 | -- DropForeignKey
5 | ALTER TABLE "projects" DROP CONSTRAINT "projects_userId_fkey";
6 |
7 | -- AddForeignKey
8 | ALTER TABLE "projects" ADD CONSTRAINT "projects_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
9 |
10 | -- AddForeignKey
11 | ALTER TABLE "feedbacks" ADD CONSTRAINT "feedbacks_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
12 |
--------------------------------------------------------------------------------
/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"
--------------------------------------------------------------------------------
/prisma/schema.prisma:
--------------------------------------------------------------------------------
1 | datasource db {
2 | provider = "postgresql"
3 | url = env("DATABASE_URL")
4 | }
5 |
6 | generator client {
7 | provider = "prisma-client-js"
8 | }
9 |
10 | model Authenticator {
11 | credentialID String @unique
12 | userId String
13 | providerAccountId String
14 | credentialPublicKey String
15 | counter Int
16 | credentialDeviceType String
17 | credentialBackedUp Boolean
18 | transports String?
19 |
20 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
21 |
22 | @@id([userId, credentialID])
23 | }
24 |
25 | model Account {
26 | userId String
27 | type String
28 | provider String
29 | providerAccountId String
30 | refresh_token String?
31 | access_token String?
32 | expires_at Int?
33 | token_type String?
34 | scope String?
35 | id_token String?
36 | session_state String?
37 |
38 | createdAt DateTime @default(now())
39 | updatedAt DateTime @updatedAt
40 |
41 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
42 |
43 | @@id([provider, providerAccountId])
44 | }
45 |
46 | model Session {
47 | sessionToken String @unique
48 | userId String
49 | expires DateTime
50 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
51 |
52 | createdAt DateTime @default(now())
53 | updatedAt DateTime @updatedAt
54 | }
55 |
56 | model User {
57 | id String @id @default(cuid())
58 | name String?
59 | email String @unique
60 | emailVerified DateTime?
61 | image String?
62 | accounts Account[]
63 | sessions Session[]
64 | projects Project[]
65 | Authenticator Authenticator[]
66 |
67 | createdAt DateTime @default(now())
68 | updatedAt DateTime @updatedAt
69 |
70 | @@map("users")
71 | }
72 |
73 | model Project {
74 | id String @id @default(cuid())
75 | name String
76 | url String @unique
77 | description String
78 | userId String
79 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
80 | feedbacks Feedback[]
81 | createdAt DateTime @default(now())
82 |
83 | @@map("projects")
84 | }
85 |
86 | model Feedback {
87 | id String @id @default(cuid())
88 | name String
89 | email String
90 | feedback String
91 | rating Int @default(3)
92 | createdAt DateTime @default(now())
93 | projectId String
94 | Project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
95 |
96 | @@map("feedbacks")
97 | }
98 |
99 | model VerificationToken {
100 | identifier String
101 | token String
102 | expires DateTime
103 |
104 | @@id([identifier, token])
105 | }
106 |
--------------------------------------------------------------------------------
/public/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avayyyyyyy/Opinify/28d07c505e5d12896fa341847e59dbe50567f186/public/Logo.png
--------------------------------------------------------------------------------
/public/peerlist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avayyyyyyy/Opinify/28d07c505e5d12896fa341847e59dbe50567f186/public/peerlist.png
--------------------------------------------------------------------------------
/public/process1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avayyyyyyy/Opinify/28d07c505e5d12896fa341847e59dbe50567f186/public/process1.png
--------------------------------------------------------------------------------
/public/process2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avayyyyyyy/Opinify/28d07c505e5d12896fa341847e59dbe50567f186/public/process2.png
--------------------------------------------------------------------------------
/public/process3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avayyyyyyy/Opinify/28d07c505e5d12896fa341847e59dbe50567f186/public/process3.png
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const config: 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 | animation: {
22 | 'border-beam': 'border-beam calc(var(--duration)*1s) infinite linear',
23 | 'accordion-down': 'accordion-down 0.2s ease-out',
24 | 'accordion-up': 'accordion-up 0.2s ease-out',
25 | 'logo-cloud': 'logo-cloud 30s linear infinite',
26 | rainbow: 'rainbow var(--speed, 2s) infinite linear'
27 | },
28 | keyframes: {
29 | 'border-beam': {
30 | '100%': {
31 | 'offset-distance': '100%'
32 | }
33 | },
34 | 'accordion-down': {
35 | from: {
36 | height: '0'
37 | },
38 | to: {
39 | height: 'var(--radix-accordion-content-height)'
40 | }
41 | },
42 | 'accordion-up': {
43 | from: {
44 | height: 'var(--radix-accordion-content-height)'
45 | },
46 | to: {
47 | height: '0'
48 | }
49 | },
50 | 'logo-cloud': {
51 | from: {
52 | transform: 'translateX(0)'
53 | },
54 | to: {
55 | transform: 'translateX(calc(-100% - 4rem))'
56 | }
57 | },
58 | rainbow: {
59 | '0%': {
60 | 'background-position': '0%'
61 | },
62 | '100%': {
63 | 'background-position': '200%'
64 | }
65 | }
66 | },
67 | colors: {
68 | border: 'hsl(var(--border))',
69 | input: 'hsl(var(--input))',
70 | ring: 'hsl(var(--ring))',
71 | background: 'hsl(var(--background))',
72 | foreground: 'hsl(var(--foreground))',
73 | primary: {
74 | DEFAULT: 'hsl(var(--primary))',
75 | foreground: 'hsl(var(--primary-foreground))'
76 | },
77 | secondary: {
78 | DEFAULT: 'hsl(var(--secondary))',
79 | foreground: 'hsl(var(--secondary-foreground))'
80 | },
81 | destructive: {
82 | DEFAULT: 'hsl(var(--destructive))',
83 | foreground: 'hsl(var(--destructive-foreground))'
84 | },
85 | muted: {
86 | DEFAULT: 'hsl(var(--muted))',
87 | foreground: 'hsl(var(--muted-foreground))'
88 | },
89 | accent: {
90 | DEFAULT: 'hsl(var(--accent))',
91 | foreground: 'hsl(var(--accent-foreground))'
92 | },
93 | popover: {
94 | DEFAULT: 'hsl(var(--popover))',
95 | foreground: 'hsl(var(--popover-foreground))'
96 | },
97 | card: {
98 | DEFAULT: 'hsl(var(--card))',
99 | foreground: 'hsl(var(--card-foreground))'
100 | },
101 | 'color-1': 'hsl(var(--color-1))',
102 | 'color-2': 'hsl(var(--color-2))',
103 | 'color-3': 'hsl(var(--color-3))',
104 | 'color-4': 'hsl(var(--color-4))',
105 | 'color-5': 'hsl(var(--color-5))'
106 | },
107 | borderRadius: {
108 | lg: 'var(--radius)',
109 | md: 'calc(var(--radius) - 2px)',
110 | sm: 'calc(var(--radius) - 4px)'
111 | }
112 | }
113 | },
114 | plugins: [require("tailwindcss-animate")],
115 | };
116 |
117 | export default config;
118 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
|