diff --git a/.env b/.env index 922699a..b4f8da8 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ DATABASE_URL=postgresql://localhost:5432/seistart -NEXTAUTH_JWT_SECRET=KyxVXUR2EIF1MuesX9ygnnsfeQyu7ExK_2suK6lLqWA4evzzDjBTR1KF__frGgWGjFoUCk1p2PPpBIeG5tVydQ \ No newline at end of file +NEXTAUTH_JWT_SECRET=KyxVXUR2EIF1MuesX9ygnnsfeQyu7ExK_2suK6lLqWA4evzzDjBTR1KF__frGgWGjFoUCk1p2PPpBIeG5tVydQ diff --git a/app/(app)/projects/[slug]/ProjectLinks.tsx b/app/(app)/projects/[slug]/ProjectLinks.tsx new file mode 100644 index 0000000..8bb6acd --- /dev/null +++ b/app/(app)/projects/[slug]/ProjectLinks.tsx @@ -0,0 +1,11 @@ +import Link from "next/link" +import React from "react" + +interface ProjectLinksProps { + url: string + children: React.ReactNode +} + +export default function ProjectLinks({ url, children }: ProjectLinksProps) { + return url ? {children} : <> +} diff --git a/app/(app)/projects/[slug]/page.tsx b/app/(app)/projects/[slug]/page.tsx index cd030d2..c01b213 100644 --- a/app/(app)/projects/[slug]/page.tsx +++ b/app/(app)/projects/[slug]/page.tsx @@ -1,4 +1,12 @@ +import { AspectRatio } from "@/components/ui/aspect-ratio" import { getProjectBySlugAction } from "@/server-actions/projects/projects.actions" +import { TwitterIcon } from "lucide-react" +import Image from "next/image" +import Link from "next/link" +import { FaDiscord, FaTelegram } from "react-icons/fa" +import { GoDotFill } from "react-icons/go" +import { IoBookOutline } from "react-icons/io5" +import ProjectLinks from "./ProjectLinks" export const dynamic = "force-dynamic" @@ -15,11 +23,100 @@ export async function generateMetadata({ } } +const images = [ + { + url: "/images/noimage.webp", + }, + + { + url: "/images/noimage.webp", + }, + + { + url: "/images/noimage.webp", + }, +] + export default async function ProjectPage({ params, }: { params: { slug: string } }) { const { project } = await getProjectBySlugAction(params.slug) - return <>{project.name} + return ( +
+
+ {`< All Projects`} +
+ {project.name} +
+

+ {project.tokenName} +

+

+ {project.description} +

+
+ {project.tags.map((tag, index) => ( + + {tag} + + ))} +
+
+
+
+
+
+ + {project.isLive ? "Live" : "Offline"} +
+
+
+

Official Links:

+
+ + + + + + + + + + + + +
+
+
+
+
+ {images.map((image, index) => ( + + {`image`} + + ))} +
+
+ ) } diff --git a/bun.lockb b/bun.lockb index 570d829..4be527b 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/ui/aspect-ratio.tsx b/components/ui/aspect-ratio.tsx new file mode 100644 index 0000000..d6a5226 --- /dev/null +++ b/components/ui/aspect-ratio.tsx @@ -0,0 +1,7 @@ +"use client" + +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" + +const AspectRatio = AspectRatioPrimitive.Root + +export { AspectRatio } diff --git a/database/migrations/0001_loving_blue_shield.sql b/database/migrations/0001_loving_blue_shield.sql new file mode 100644 index 0000000..7d8c5fc --- /dev/null +++ b/database/migrations/0001_loving_blue_shield.sql @@ -0,0 +1 @@ +ALTER TABLE "projects" DROP COLUMN IF EXISTS "wechat"; \ No newline at end of file diff --git a/database/migrations/meta/0001_snapshot.json b/database/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..29250ec --- /dev/null +++ b/database/migrations/meta/0001_snapshot.json @@ -0,0 +1,348 @@ +{ + "id": "6b77787d-cb30-4f3e-a3d8-886c9e7d1821", + "prevId": "ddebb7e5-6179-4815-bcc8-b821bc8d049a", + "version": "5", + "dialect": "pg", + "tables": { + "session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "hashed_password": { + "name": "hashed_password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + } + }, + "projects": { + "name": "projects", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "token_name": { + "name": "token_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "token_supply": { + "name": "token_supply", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "release_date": { + "name": "release_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "summary": { + "name": "summary", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "is_live": { + "name": "is_live", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "none": { + "name": "none", + "type": "stage", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "community_size": { + "name": "community_size", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "project_type": { + "name": "project_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "website": { + "name": "website", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "whitepaper": { + "name": "whitepaper", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "twitter": { + "name": "twitter", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "discord": { + "name": "discord", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "telegram": { + "name": "telegram", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "contact_name": { + "name": "contact_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "contact_email": { + "name": "contact_email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "projects_user_id_user_id_fk": { + "name": "projects_user_id_user_id_fk", + "tableFrom": "projects", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "projects_slug_unique": { + "name": "projects_slug_unique", + "nullsNotDistinct": false, + "columns": ["slug"] + } + } + }, + "project_tags": { + "name": "project_tags", + "schema": "", + "columns": { + "project_id": { + "name": "project_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "tag_id": { + "name": "tag_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "project_tags_project_id_projects_id_fk": { + "name": "project_tags_project_id_projects_id_fk", + "tableFrom": "project_tags", + "tableTo": "projects", + "columnsFrom": ["project_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "project_tags_tag_id_tags_id_fk": { + "name": "project_tags_tag_id_tags_id_fk", + "tableFrom": "project_tags", + "tableTo": "tags", + "columnsFrom": ["tag_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "project_tags_user_id_user_id_fk": { + "name": "project_tags_user_id_user_id_fk", + "tableFrom": "project_tags", + "tableTo": "user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "tags": { + "name": "tags", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "tags_name_unique": { + "name": "tags_name_unique", + "nullsNotDistinct": false, + "columns": ["name"] + } + } + } + }, + "enums": { + "stage": { + "name": "stage", + "values": { + "Mainnet": "Mainnet", + "Testnet": "Testnet", + "Devnet": "Devnet", + "Local/Private": "Local/Private" + } + } + }, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/database/schemas/projects.schema.ts b/database/schemas/projects.schema.ts index d5d0854..34a884b 100644 --- a/database/schemas/projects.schema.ts +++ b/database/schemas/projects.schema.ts @@ -85,7 +85,7 @@ export const ProjectTable = pgTable("project", { const BaseSchema = createSelectSchema(ProjectTable).omit(timestamps) -const ProjectWithTagsSchema = BaseSchema.extend({ +export const ProjectWithTagsSchema = BaseSchema.extend({ tags: z.array(z.string()).max(3), mainTag: z.string(), website: z.string().url(), diff --git a/mocks/projects.mocks.ts b/mocks/projects.mocks.ts index a1682e1..c8007b7 100644 --- a/mocks/projects.mocks.ts +++ b/mocks/projects.mocks.ts @@ -1,5 +1,5 @@ import { - InsertProjectSchema, + ProjectWithTagsSchema, ProjectsResponseSchema, projectTagSchema, } from "@/database/schemas/projects.schema" @@ -41,10 +41,17 @@ export const mockProjects = (size: number) => { }) } -export const getMockProject = getMockFn(InsertProjectSchema) +export const getMockProject = getMockFn(ProjectWithTagsSchema) export const mockProject = getMockProject({ - overrideFn: (entry) => ({ - ...entry, - mainTag: "Dex", - }), + overrideFn: (project) => { + const _projectType = tags[Math.floor(Math.random() * tags.length)] + project.mainTag = _projectType + project.tags = [_projectType, ...generateTags([], _projectType)] + project.description = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam" + + return { + ...project, + } + }, }) diff --git a/package.json b/package.json index b1ecfb8..86b6cfb 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@lucia-auth/adapter-drizzle": "^1.0.2", "@node-rs/argon2": "^1.8.0", "@node-rs/bcrypt": "^1.9.2", + "@radix-ui/react-aspect-ratio": "^1.0.3", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", diff --git a/public/images/noimage.webp b/public/images/noimage.webp new file mode 100644 index 0000000..8702aaa Binary files /dev/null and b/public/images/noimage.webp differ diff --git a/public/images/sei.jpg b/public/images/sei.jpg new file mode 100644 index 0000000..2ffee1d Binary files /dev/null and b/public/images/sei.jpg differ