feat: cv verifier
This commit is contained in:
parent
4dd699f08c
commit
194b4b0808
24 changed files with 2199 additions and 70 deletions
11
.prettierrc
Normal file
11
.prettierrc
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-astro"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": "*.astro",
|
||||||
|
"options": {
|
||||||
|
"parser": "astro"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -9,13 +9,17 @@ import tailwind from "@astrojs/tailwind";
|
||||||
import icon from "astro-icon";
|
import icon from "astro-icon";
|
||||||
import { remarkReadingTime } from "./src/remark/remark-reading-time";
|
import { remarkReadingTime } from "./src/remark/remark-reading-time";
|
||||||
|
|
||||||
|
import cloudflare from "@astrojs/cloudflare";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
prefetch: {
|
prefetch: {
|
||||||
defaultStrategy: "hover",
|
defaultStrategy: "hover",
|
||||||
prefetchAll: true,
|
prefetchAll: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
site: "https://daichendt.one",
|
site: "https://daichendt.one",
|
||||||
|
|
||||||
integrations: [
|
integrations: [
|
||||||
mdx({
|
mdx({
|
||||||
remarkPlugins: [remarkEmoji, remarkReadingTime],
|
remarkPlugins: [remarkEmoji, remarkReadingTime],
|
||||||
|
|
@ -24,4 +28,10 @@ export default defineConfig({
|
||||||
tailwind(),
|
tailwind(),
|
||||||
icon(),
|
icon(),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
adapter: cloudflare({
|
||||||
|
platformProxy: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
24
drizzle.config.ts
Normal file
24
drizzle.config.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import type { Config } from "drizzle-kit";
|
||||||
|
|
||||||
|
const { LOCAL_DB_PATH, DB_ID, D1_TOKEN, CF_ACCOUNT_ID } = process.env;
|
||||||
|
|
||||||
|
// Use better-sqlite driver for local development
|
||||||
|
export default LOCAL_DB_PATH
|
||||||
|
? ({
|
||||||
|
schema: "./src/db/schema.ts",
|
||||||
|
dialect: "sqlite",
|
||||||
|
dbCredentials: {
|
||||||
|
url: LOCAL_DB_PATH,
|
||||||
|
},
|
||||||
|
} satisfies Config)
|
||||||
|
: ({
|
||||||
|
schema: "./src/db/schema.ts",
|
||||||
|
out: "./migrations",
|
||||||
|
dialect: "sqlite",
|
||||||
|
driver: "d1-http",
|
||||||
|
dbCredentials: {
|
||||||
|
databaseId: DB_ID!,
|
||||||
|
token: D1_TOKEN!,
|
||||||
|
accountId: CF_ACCOUNT_ID!,
|
||||||
|
},
|
||||||
|
} satisfies Config);
|
||||||
8
migrations/0000_naive_tarantula.sql
Normal file
8
migrations/0000_naive_tarantula.sql
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE `cv` (
|
||||||
|
`uuid` text PRIMARY KEY NOT NULL,
|
||||||
|
`company_name` text NOT NULL,
|
||||||
|
`created` integer,
|
||||||
|
`author` text NOT NULL,
|
||||||
|
`created_for` text NOT NULL,
|
||||||
|
`status` text DEFAULT 'pending'
|
||||||
|
);
|
||||||
15
migrations/0001_confused_wendell_rand.sql
Normal file
15
migrations/0001_confused_wendell_rand.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
PRAGMA foreign_keys=OFF;--> statement-breakpoint
|
||||||
|
CREATE TABLE `__new_cv` (
|
||||||
|
`uuid` text PRIMARY KEY NOT NULL,
|
||||||
|
`company_name` text NOT NULL,
|
||||||
|
`created` integer,
|
||||||
|
`author` text NOT NULL,
|
||||||
|
`purpose` text NOT NULL,
|
||||||
|
`tooling` text NOT NULL,
|
||||||
|
`status` text DEFAULT 'active'
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
INSERT INTO `__new_cv`("uuid", "company_name", "created", "author", "purpose", "tooling", "status") SELECT "uuid", "company_name", "created", "author", "purpose", "tooling", "status" FROM `cv`;--> statement-breakpoint
|
||||||
|
DROP TABLE `cv`;--> statement-breakpoint
|
||||||
|
ALTER TABLE `__new_cv` RENAME TO `cv`;--> statement-breakpoint
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
71
migrations/meta/0000_snapshot.json
Normal file
71
migrations/meta/0000_snapshot.json
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "ed238646-2f39-4026-8075-4ddf059cc6f7",
|
||||||
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
|
"tables": {
|
||||||
|
"cv": {
|
||||||
|
"name": "cv",
|
||||||
|
"columns": {
|
||||||
|
"uuid": {
|
||||||
|
"name": "uuid",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"company_name": {
|
||||||
|
"name": "company_name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"name": "created",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "author",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_for": {
|
||||||
|
"name": "created_for",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'pending'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"views": {},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
migrations/meta/0001_snapshot.json
Normal file
80
migrations/meta/0001_snapshot.json
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "a68f3965-0dd6-46c6-af01-4f96061e8b11",
|
||||||
|
"prevId": "ed238646-2f39-4026-8075-4ddf059cc6f7",
|
||||||
|
"tables": {
|
||||||
|
"cv": {
|
||||||
|
"name": "cv",
|
||||||
|
"columns": {
|
||||||
|
"uuid": {
|
||||||
|
"name": "uuid",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"company_name": {
|
||||||
|
"name": "company_name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"name": "created",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "author",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"purpose": {
|
||||||
|
"name": "purpose",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"tooling": {
|
||||||
|
"name": "tooling",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'active'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"views": {},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {
|
||||||
|
"\"cv\".\"created_for\"": "\"cv\".\"purpose\""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
migrations/meta/_journal.json
Normal file
20
migrations/meta/_journal.json
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"idx": 0,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1735731743025,
|
||||||
|
"tag": "0000_naive_tarantula",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 1,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1735735966188,
|
||||||
|
"tag": "0001_confused_wendell_rand",
|
||||||
|
"breakpoints": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
18
package.json
18
package.json
|
|
@ -6,19 +6,29 @@
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"build": "astro build",
|
"build": "astro build",
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"astro": "astro"
|
"astro": "astro",
|
||||||
|
"db:generate": "drizzle-kit generate",
|
||||||
|
"db:migrate:local": "wrangler d1 migrations apply cv-verification --local",
|
||||||
|
"db:migrate:prod": "wrangler d1 migrations apply cv-verification --remote",
|
||||||
|
"db:migrate:preview": "wrangler d1 migrations apply --env preview d1-demo-preview-db --remote",
|
||||||
|
"db:studio:local": "LOCAL_DB_PATH=$(find .wrangler/state/v3/d1/miniflare-D1DatabaseObject -type f -name '*.sqlite' -print -quit) drizzle-kit studio",
|
||||||
|
"db:studio:preview": "source .drizzle.env && DB_ID='yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy' drizzle-kit studio",
|
||||||
|
"db:studio:prod": "source .drizzle.env && DB_ID='ae0b9867-26f2-4a5b-8aa6-805a86792662' drizzle-kit studio"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.9.4",
|
"@astrojs/check": "^0.9.4",
|
||||||
|
"@astrojs/cloudflare": "^12.1.0",
|
||||||
"@astrojs/mdx": "^4.0.1",
|
"@astrojs/mdx": "^4.0.1",
|
||||||
"@astrojs/rss": "^4.0.10",
|
"@astrojs/rss": "^4.0.10",
|
||||||
"@astrojs/sitemap": "^3.2.1",
|
"@astrojs/sitemap": "^3.2.1",
|
||||||
"@astrojs/tailwind": "^5.1.3",
|
"@astrojs/tailwind": "^5.1.3",
|
||||||
|
"@cloudflare/workers-types": "^4.20241230.0",
|
||||||
"@fontsource/ubuntu": "^5.1.0",
|
"@fontsource/ubuntu": "^5.1.0",
|
||||||
"@iconify-json/mdi": "^1.2.1",
|
"@iconify-json/mdi": "^1.2.1",
|
||||||
"@iconify-json/simple-icons": "^1.2.14",
|
"@iconify-json/simple-icons": "^1.2.14",
|
||||||
"astro": "^5.0.3",
|
"astro": "^5.0.3",
|
||||||
"astro-icon": "^1.1.4",
|
"astro-icon": "^1.1.4",
|
||||||
|
"drizzle-orm": "^0.38.3",
|
||||||
"mdast-util-to-string": "^4.0.0",
|
"mdast-util-to-string": "^4.0.0",
|
||||||
"reading-time": "^1.5.0",
|
"reading-time": "^1.5.0",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
|
|
@ -27,6 +37,12 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwind-plugin/expose-colors": "^1.1.8",
|
"@tailwind-plugin/expose-colors": "^1.1.8",
|
||||||
|
"@types/node": "^22.10.3",
|
||||||
|
"better-sqlite3": "^11.7.0",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"drizzle-kit": "^0.30.1",
|
||||||
|
"prettier": "^3.4.2",
|
||||||
|
"prettier-plugin-astro": "^0.14.1",
|
||||||
"remark-emoji": "^5.0.1"
|
"remark-emoji": "^5.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1737
pnpm-lock.yaml
generated
1737
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
51
src/components/verification/DataTable.astro
Normal file
51
src/components/verification/DataTable.astro
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
import type { InferSelectModel } from "drizzle-orm";
|
||||||
|
import type { cvTable } from "../../db/schema";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
cv: InferSelectModel<typeof cvTable>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { cv } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-6">
|
||||||
|
<ul class="space-y-4 mb-0">
|
||||||
|
<li class="flex items-start">
|
||||||
|
<span class="text-gray-500 dark:text-gray-400 min-w-32"> UUID: </span>
|
||||||
|
<span class="text-gray-800 dark:text-gray-200 font-medium">
|
||||||
|
{cv.uuid}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-start">
|
||||||
|
<span class="text-gray-500 dark:text-gray-400 min-w-32">
|
||||||
|
Issued by:
|
||||||
|
</span>
|
||||||
|
<span class="text-gray-800 dark:text-gray-200 font-medium">
|
||||||
|
{cv.author}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-start">
|
||||||
|
<span class="text-gray-500 dark:text-gray-400 min-w-32">
|
||||||
|
Issued to:
|
||||||
|
</span>
|
||||||
|
<span class="text-gray-800 dark:text-gray-200 font-medium">
|
||||||
|
{cv.company_name}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-start">
|
||||||
|
<span class="text-gray-500 dark:text-gray-400 min-w-32">
|
||||||
|
Issue date:
|
||||||
|
</span>
|
||||||
|
<span class="text-gray-800 dark:text-gray-200 font-medium">
|
||||||
|
{cv.created?.toLocaleString()}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-start">
|
||||||
|
<span class="text-gray-500 dark:text-gray-400 min-w-32"> Purpose: </span>
|
||||||
|
<span class="text-gray-800 dark:text-gray-200 font-medium">
|
||||||
|
{cv.purpose}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
5
src/components/verification/NoCV.astro
Normal file
5
src/components/verification/NoCV.astro
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="text-center p-8 bg-red-50 dark:bg-red-950 rounded-lg shadow-sm">
|
||||||
|
<p class="text-red-600 dark:text-red-400 text-lg font-medium">
|
||||||
|
No CV found with this UUID.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
20
src/components/verification/Revoked.astro
Normal file
20
src/components/verification/Revoked.astro
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<div class="flex items-center justify-center gap-2 mb-4">
|
||||||
|
<div class="bg-red-100 dark:bg-red-900 p-2 rounded-full">
|
||||||
|
<svg
|
||||||
|
class="w-6 h-6 text-red-600 dark:text-red-400"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M6 18L18 6M6 6l12 12"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h2 class="text-2xl font-bold text-red-600 dark:text-red-400">Revoked CV</h2>
|
||||||
|
</div>
|
||||||
|
<p class="text-red-600 dark:text-red-400 text-lg">
|
||||||
|
This CV has been revoked and is no longer valid.
|
||||||
|
</p>
|
||||||
36
src/components/verification/Verified.astro
Normal file
36
src/components/verification/Verified.astro
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
import type { InferSelectModel } from "drizzle-orm";
|
||||||
|
import type { cvTable } from "../../db/schema";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
cv: InferSelectModel<typeof cvTable>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { cv } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2 mb-6">
|
||||||
|
<div class="bg-green-100 dark:bg-green-900 p-2 rounded-full">
|
||||||
|
<svg
|
||||||
|
class="w-6 h-6 text-green-600 dark:text-green-400"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M5 13l4 4L19 7"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h2 class="text-2xl font-bold text-gray-800 dark:text-gray-100">
|
||||||
|
Verified CV
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
This CV was issued and verified by
|
||||||
|
<span class="font-semibold">{cv.author}</span>, for{" "}
|
||||||
|
<span class="font-semibold">{cv.company_name}</span>
|
||||||
|
</p>
|
||||||
15
src/db/schema.ts
Normal file
15
src/db/schema.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
export const cvTable = sqliteTable("cv", {
|
||||||
|
uuid: text("uuid").primaryKey(),
|
||||||
|
company_name: text("company_name").notNull(),
|
||||||
|
created: integer("created", {
|
||||||
|
mode: "timestamp_ms",
|
||||||
|
}),
|
||||||
|
author: text("author").notNull(),
|
||||||
|
purpose: text("purpose").notNull(),
|
||||||
|
tooling: text("tooling").notNull(),
|
||||||
|
status: text("status", {
|
||||||
|
enum: ["active", "revoked"],
|
||||||
|
}).default("active"),
|
||||||
|
});
|
||||||
10
src/env.d.ts
vendored
Normal file
10
src/env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
// src/env.d.ts
|
||||||
|
|
||||||
|
/// <reference path="../.astro/types.d.ts" />
|
||||||
|
/// <reference types="astro/client" />
|
||||||
|
|
||||||
|
type Runtime = import("@astrojs/cloudflare").Runtime<Env>;
|
||||||
|
|
||||||
|
declare namespace App {
|
||||||
|
interface Locals extends Runtime {}
|
||||||
|
}
|
||||||
39
src/pages/cv_verification/index.astro
Normal file
39
src/pages/cv_verification/index.astro
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { drizzle } from "drizzle-orm/d1";
|
||||||
|
import { cvTable } from "../../db/schema";
|
||||||
|
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||||
|
import DataTable from "../../components/verification/DataTable.astro";
|
||||||
|
import NoCV from "../../components/verification/NoCV.astro";
|
||||||
|
import Verified from "../../components/verification/Verified.astro";
|
||||||
|
import Revoked from "../../components/verification/Revoked.astro";
|
||||||
|
|
||||||
|
export const prerender = false;
|
||||||
|
const uuid = Astro.url.searchParams.get("uuid");
|
||||||
|
|
||||||
|
const db = drizzle(Astro.locals.runtime.env.DB);
|
||||||
|
|
||||||
|
const cv = uuid
|
||||||
|
? await db.select().from(cvTable).where(eq(cvTable.uuid, uuid))
|
||||||
|
: [];
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout title="CV Verification">
|
||||||
|
<section class="max-w-4xl mx-auto min-h-screen">
|
||||||
|
{
|
||||||
|
cv.length === 0 ? (
|
||||||
|
<NoCV />
|
||||||
|
) : cv[0].status !== "active" ? (
|
||||||
|
<div class="text-center p-8 bg-red-50 dark:bg-red-950 rounded-lg shadow-sm">
|
||||||
|
<Revoked />
|
||||||
|
<DataTable cv={cv[0]} />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div class="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-lg">
|
||||||
|
<Verified cv={cv[0]} />
|
||||||
|
<DataTable cv={cv[0]} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
</BaseLayout>
|
||||||
|
|
@ -4,7 +4,7 @@ import BaseLayout from "../layouts/BaseLayout.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout>
|
<BaseLayout>
|
||||||
<h1>Hi, my name is Alex!</h1>
|
<h1 class="text-4xl sm:text-5xl">Hi, my name is Alex!</h1>
|
||||||
<p>
|
<p>
|
||||||
I am a software engineer, Linux enthusiast and a friend of lightweight,
|
I am a software engineer, Linux enthusiast and a friend of lightweight,
|
||||||
resilient systems.
|
resilient systems.
|
||||||
|
|
|
||||||
5
worker-configuration.d.ts
vendored
Normal file
5
worker-configuration.d.ts
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// Generated by Wrangler by running `wrangler types`
|
||||||
|
|
||||||
|
interface Env {
|
||||||
|
DB: D1Database;
|
||||||
|
}
|
||||||
4
wrangler.toml
Normal file
4
wrangler.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
[[d1_databases]]
|
||||||
|
binding = "DB"
|
||||||
|
database_name = "cv-verification"
|
||||||
|
database_id = "ae0b9867-26f2-4a5b-8aa6-805a86792662"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue