feat: implement initial fullstack portfolio application including dashboard, CMS, and analytics features.
This commit is contained in:
38
src/lib/constant.ts
Normal file
38
src/lib/constant.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export const NavLinks = [
|
||||
{ label: "About", href: "#about" },
|
||||
{ label: "Stack", href: "#stack" },
|
||||
{ label: "Projects", href: "#projects" },
|
||||
{ label: "Experience", href: "#experience" },
|
||||
{ label: "Contact", href: "#contact" },
|
||||
];
|
||||
|
||||
export const ContactUrls = {
|
||||
github: "https://github.com/Dzuuul",
|
||||
linkedin: "https://www.linkedin.com/in/dzulfikrimaulana",
|
||||
email: "mailto:developer@dzulfikri.com?subject=Inquiry:%20Fullstack%20Developer%20Opportunity%20-%20[Company/Project%20Name]&body=Hi%20Fikri,%0D%0A%0D%0AI%20am%20[Name]%20from%20[Company/Organization%20Name].%0D%0A%0D%0AI%20recently%20explored%20your%20portfolio%20and%20was%20impressed%20by%20your%20work%20as%20a%20Fullstack%20Developer.%20I%20would%20like%20to%20discuss%20a%20potential%20opportunity%20with%20you,%20whether%20it%20be%20for%20a%20career%20role%20within%20our%20team%20or%20a%20professional%20collaboration%20on%20an%20upcoming%20project.%0D%0A%0D%0AAre%20you%20available%20for%20a%20brief%20introductory%20call%20or%20a%20chat%20sometime%20this%20week%20to%20discuss%20this%20further?%0D%0A%0D%0ABest%20regards,%0D%0A[Name]%0D%0A[LinkedIn%20Profile/Contact%20Info]"
|
||||
}
|
||||
|
||||
export const HeroSection = {
|
||||
badge: "Available for opportunities",
|
||||
headline: "Fullstack",
|
||||
headline2: "Developer",
|
||||
tagline1: "Specializing in Next.js & NestJS",
|
||||
tagline2:
|
||||
"Building scalable web applications with Next.js and NestJS, focused on performance, clean architecture, and real-world systems.",
|
||||
image: "/images/hero-portrait.png",
|
||||
};
|
||||
|
||||
export const AboutSection = {
|
||||
title: "About Me",
|
||||
description: "",
|
||||
};
|
||||
|
||||
export const ArchitectureSection = {
|
||||
title: "Architecture",
|
||||
description: "",
|
||||
};
|
||||
|
||||
export const ContactSection = {
|
||||
title: "Contact Me",
|
||||
description: "",
|
||||
};
|
||||
23
src/lib/prisma.ts
Normal file
23
src/lib/prisma.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { Pool } from "pg";
|
||||
import { PrismaPg } from "@prisma/adapter-pg";
|
||||
|
||||
const connectionString = `${process.env.DATABASE_URL}`;
|
||||
const pool = new Pool({ connectionString });
|
||||
const adapter = new PrismaPg(pool);
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma: PrismaClient | undefined;
|
||||
};
|
||||
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
adapter,
|
||||
log:
|
||||
process.env.NODE_ENV === "development"
|
||||
? ["query", "error", "warn"]
|
||||
: ["error"],
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
||||
23
src/lib/s3.ts
Normal file
23
src/lib/s3.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
|
||||
|
||||
const s3 = new S3Client({
|
||||
region: "auto",
|
||||
endpoint: process.env.R2_ENDPOINT,
|
||||
credentials: {
|
||||
accessKeyId: process.env.R2_ACCESS_KEY!,
|
||||
secretAccessKey: process.env.R2_SECRET_KEY!,
|
||||
},
|
||||
});
|
||||
|
||||
export async function uploadFile(file: File) {
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
|
||||
await s3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: process.env.R2_BUCKET_NAME,
|
||||
Key: file.name,
|
||||
Body: buffer,
|
||||
ContentType: file.type,
|
||||
}),
|
||||
);
|
||||
}
|
||||
6
src/lib/utils.ts
Normal file
6
src/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
10
src/lib/visitor.ts
Normal file
10
src/lib/visitor.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export function getVisitorId() {
|
||||
let visitorId = localStorage.getItem("visitor_id");
|
||||
|
||||
if (!visitorId) {
|
||||
visitorId = crypto.randomUUID();
|
||||
localStorage.setItem("visitor_id", visitorId);
|
||||
}
|
||||
|
||||
return visitorId;
|
||||
}
|
||||
Reference in New Issue
Block a user