diff --git a/messages/en.json b/messages/en.json index 17e7921..efee0bc 100644 --- a/messages/en.json +++ b/messages/en.json @@ -7,7 +7,7 @@ }, "Hero": { "greeting": "Hi, I'm", - "name": "Yolando.", + "name": "Yolando Manullang.", "badge": "Available for opportunities", "titlePart1": "Building", "titleHighlight": "Secure, Scalable", @@ -142,4 +142,4 @@ "backToTop": "Back to top", "copyright": "Yolando. Built with Next.js & crafted with purpose." } -} +} \ No newline at end of file diff --git a/messages/id.json b/messages/id.json index 6123e5e..f58c982 100644 --- a/messages/id.json +++ b/messages/id.json @@ -7,7 +7,7 @@ }, "Hero": { "greeting": "Hai, saya", - "name": "Yolando.", + "name": "Yolando Manullang.", "badge": "Tersedia untuk peluang baru", "titlePart1": "Membangun Sistem", "titleHighlight": "Aman & Skalabel", @@ -142,4 +142,4 @@ "backToTop": "Kembali ke atas", "copyright": "Yolando. Dibangun dengan Next.js & dibuat dengan penuh tujuan." } -} +} \ No newline at end of file diff --git a/prisma/migrations/20260331193217_add_experience_model/migration.sql b/prisma/migrations/20260331193217_add_experience_model/migration.sql new file mode 100644 index 0000000..f0113f2 --- /dev/null +++ b/prisma/migrations/20260331193217_add_experience_model/migration.sql @@ -0,0 +1,81 @@ +-- CreateTable +CREATE TABLE "users" ( + "id" UUID NOT NULL, + "email" TEXT NOT NULL, + "password_hash" TEXT NOT NULL, + "name" TEXT NOT NULL, + + CONSTRAINT "users_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "projects" ( + "id" UUID NOT NULL, + "title" TEXT NOT NULL, + "slug" TEXT NOT NULL, + "description" TEXT NOT NULL, + "image_url" TEXT, + "repo_url" TEXT, + "live_url" TEXT, + "category" TEXT NOT NULL, + "is_published" BOOLEAN NOT NULL DEFAULT false, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "projects_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "skills" ( + "id" UUID NOT NULL, + "name" TEXT NOT NULL, + "icon_name" TEXT, + "category" TEXT NOT NULL, + + CONSTRAINT "skills_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "project_skills" ( + "project_id" UUID NOT NULL, + "skill_id" UUID NOT NULL, + + CONSTRAINT "project_skills_pkey" PRIMARY KEY ("project_id","skill_id") +); + +-- CreateTable +CREATE TABLE "messages" ( + "id" UUID NOT NULL, + "sender_name" TEXT NOT NULL, + "sender_email" TEXT NOT NULL, + "content" TEXT NOT NULL, + "is_read" BOOLEAN NOT NULL DEFAULT false, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "messages_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "experiences" ( + "id" UUID NOT NULL, + "year" TEXT NOT NULL, + "title" TEXT NOT NULL, + "company" TEXT NOT NULL, + "description" TEXT NOT NULL, + "achievements" JSONB NOT NULL DEFAULT '[]', + "order" INTEGER NOT NULL DEFAULT 0, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "experiences_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "users_email_key" ON "users"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "projects_slug_key" ON "projects"("slug"); + +-- AddForeignKey +ALTER TABLE "project_skills" ADD CONSTRAINT "project_skills_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "project_skills" ADD CONSTRAINT "project_skills_skill_id_fkey" FOREIGN KEY ("skill_id") REFERENCES "skills"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a9f1541..e9bc09a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -66,3 +66,16 @@ model Message { @@map("messages") } + +model Experience { + id String @id @default(uuid()) @db.Uuid + year String + title String + company String + description String @db.Text + achievements Json @default("[]") + order Int @default(0) + createdAt DateTime @default(now()) @map("created_at") + + @@map("experiences") +} diff --git a/public/uploads/1774986132810-Screenshot_2026-03-28_205042.png b/public/uploads/1774986132810-Screenshot_2026-03-28_205042.png new file mode 100644 index 0000000..6ed64fd Binary files /dev/null and b/public/uploads/1774986132810-Screenshot_2026-03-28_205042.png differ diff --git a/src/app/[locale]/admin/dashboard/experience/[id]/edit/page.tsx b/src/app/[locale]/admin/dashboard/experience/[id]/edit/page.tsx new file mode 100644 index 0000000..c2883fd --- /dev/null +++ b/src/app/[locale]/admin/dashboard/experience/[id]/edit/page.tsx @@ -0,0 +1,36 @@ +import { prisma } from "@/core/db/prisma"; +import { verifySession } from "@/core/security/session"; +import { redirect } from "@/i18n/routing"; +import { getLocale } from "next-intl/server"; +import { notFound } from "next/navigation"; +import { ExperienceForm } from "@/features/experience/experience-form"; + +export default async function EditExperiencePage({ + params, +}: { + params: Promise<{ id: string }>; +}) { + const session = await verifySession(); + const locale = await getLocale(); + if (!session) redirect({ href: "/admin/login", locale }); + + const { id } = await params; + const experience = await prisma.experience.findUnique({ where: { id } }); + if (!experience) notFound(); + + return ( +
+ Manage your career timeline. +
++ Build your career timeline in the CMS. +
+ + Add First Entry + +
+
+ {exp.description} +
+ {Array.isArray(exp.achievements) && exp.achievements.length > 0 && ( ++ Pesan masuk dari pengunjung portfolio. +
+Belum ada pesan masuk.
++ {message.content} +
++ {new Date(message.createdAt).toLocaleString("id-ID")} +
+