diff --git a/app/pages/index.vue b/app/pages/index.vue index b0f69ec9..1a0662d4 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -3,6 +3,8 @@ const { data: postings } = await usePublicPostingsRepository(); const { data: careerSiteConfig } = useCareerSiteConfigObjectState(); const { data: seoConfig } = useSeoConfigObjectState(); +const publicConfig = useRuntimeConfig().public; + let title: string = 'Careers'; // TODO: need better defaults (this will hardly be the case); let description: string = 'Career Site'; // TODO: need better defaults (this will hardly be the case); if (seoConfig.value.title) { @@ -46,7 +48,7 @@ useSeoMeta({
- +

Powered By

Avatar diff --git a/app/utils/general.ts b/app/utils/general.ts index 5aff3302..48d7dcb0 100644 --- a/app/utils/general.ts +++ b/app/utils/general.ts @@ -32,23 +32,23 @@ export function timeAgo(date: Date) { const seconds = Math.floor((now.getTime() - date.getTime()) / 1000); let interval = Math.floor(seconds / 31536000); - if (interval > 1) { + if (interval >= 1) { return `${interval}y ago`; } interval = Math.floor(seconds / 2592000); - if (interval > 1) { + if (interval >= 1) { return `${interval}mo ago`; } interval = Math.floor(seconds / 86400); - if (interval > 1) { + if (interval >= 1) { return `${interval}d ago`; } interval = Math.floor(seconds / 3600); - if (interval > 1) { + if (interval >= 1) { return `${interval}h ago`; } interval = Math.floor(seconds / 60); - if (interval > 1) { + if (interval >= 1) { return `${interval}m ago`; } return `Just Now`; diff --git a/nuxt.config.ts b/nuxt.config.ts index adfe26a4..c07c3e62 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -66,6 +66,7 @@ export default defineNuxtConfig({ github: 'https://github.com/profilecity/vidur', discord: 'https://discord.gg/9ms5uYF8xF', twitter: 'https://x.com/profilecityhq', + vidur: 'https://profilecity.xyz/vidur', version: 'v0.0.1', }, }, diff --git a/server/db/migrations/0008_open_quentin_quire.sql b/server/db/migrations/0008_open_quentin_quire.sql new file mode 100644 index 00000000..c9adbed2 --- /dev/null +++ b/server/db/migrations/0008_open_quentin_quire.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS "review_tags" ( + "id" serial PRIMARY KEY NOT NULL, + "title" varchar(8) NOT NULL, + "parent" smallint NOT NULL +); +--> statement-breakpoint +ALTER TABLE "posting_applicants" DROP CONSTRAINT "posting_applicants_owner_id_users_id_fk"; +--> statement-breakpoint +ALTER TABLE "posting_applicants" ALTER COLUMN "owner_id" SET NOT NULL;--> statement-breakpoint +ALTER TABLE "posting_applicants" ALTER COLUMN "job_id" SET NOT NULL;--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "posting_applicants" ADD CONSTRAINT "posting_applicants_owner_id_users_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/server/db/migrations/meta/0008_snapshot.json b/server/db/migrations/meta/0008_snapshot.json new file mode 100644 index 00000000..730b42a4 --- /dev/null +++ b/server/db/migrations/meta/0008_snapshot.json @@ -0,0 +1,371 @@ +{ + "id": "36dac6d2-f744-494c-9e0c-652d8efceccf", + "prevId": "cc4af3d8-c8e8-4adf-b145-bd61742066c3", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.hooks": { + "name": "hooks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(40)", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "prefs": { + "name": "prefs", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_executed_at": { + "name": "last_executed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "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": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.job_postings": { + "name": "job_postings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(150)", + "primaryKey": false, + "notNull": true + }, + "contents": { + "name": "contents", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tags_csv": { + "name": "tags_csv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "owner_id": { + "name": "owner_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "is_published": { + "name": "is_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "total_applicants": { + "name": "total_applicants", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "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": { + "job_postings_owner_id_users_id_fk": { + "name": "job_postings_owner_id_users_id_fk", + "tableFrom": "job_postings", + "tableTo": "users", + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.metadata_entries": { + "name": "metadata_entries", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "varchar(48)", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "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": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.posting_applicants": { + "name": "posting_applicants", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "owner_id": { + "name": "owner_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "posting_applicants_owner_id_users_id_fk": { + "name": "posting_applicants_owner_id_users_id_fk", + "tableFrom": "posting_applicants", + "tableTo": "users", + "columnsFrom": ["owner_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posting_applicants_job_id_job_postings_id_fk": { + "name": "posting_applicants_job_id_job_postings_id_fk", + "tableFrom": "posting_applicants", + "tableTo": "job_postings", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.review_tags": { + "name": "review_tags", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(8)", + "primaryKey": false, + "notNull": true + }, + "parent": { + "name": "parent", + "type": "smallint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user_handles": { + "name": "user_handles", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "varchar(15)", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "user_handles_user_id_users_id_fk": { + "name": "user_handles_user_id_users_id_fk", + "tableFrom": "user_handles", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "picture": { + "name": "picture", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "top_5_skills_csv": { + "name": "top_5_skills_csv", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + } + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/server/db/migrations/meta/_journal.json b/server/db/migrations/meta/_journal.json index 6b187fc7..c4272503 100644 --- a/server/db/migrations/meta/_journal.json +++ b/server/db/migrations/meta/_journal.json @@ -57,6 +57,13 @@ "when": 1719494926824, "tag": "0007_daily_owl", "breakpoints": true + }, + { + "idx": 8, + "version": "7", + "when": 1726152541712, + "tag": "0008_open_quentin_quire", + "breakpoints": true } ] } diff --git a/server/db/schema.ts b/server/db/schema.ts index cfb2e82f..2e621726 100644 --- a/server/db/schema.ts +++ b/server/db/schema.ts @@ -1,11 +1,13 @@ import { sql } from 'drizzle-orm'; -import { boolean, integer, pgTable, text, timestamp, uuid, varchar } from 'drizzle-orm/pg-core'; +import { boolean, integer, pgTable, text, timestamp, uuid, varchar, smallint, serial } from 'drizzle-orm/pg-core'; const defaultUuidPkField = () => uuid('id') .primaryKey() .$default(() => sql`gen_random_uuid()`); +const defaultSerialPkField = () => serial('id').primaryKey(); + //---------------**************---------------- export const usersTable = pgTable('users', { @@ -46,8 +48,8 @@ export const jobPostingsTable = pgTable('job_postings', { }), isPublished: boolean('is_published').default(false).notNull(), totalApplicants: integer('total_applicants').default(0).notNull(), - createdAt: timestamp('created_at').defaultNow().notNull(), - updatedAt: timestamp('updated_at').defaultNow().notNull(), + createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export type JobPosting = typeof jobPostingsTable.$inferSelect; @@ -73,6 +75,16 @@ export type PostingApplication = typeof postingApplicantsTable.$inferSelect; //---------------**************---------------- +export const reviewTagsTable = pgTable('review_tags', { + id: defaultSerialPkField(), + title: varchar('title', { length: 8 }).notNull(), + parent: smallint('parent').notNull(), +}); + +export type ReviewTag = typeof reviewTagsTable.$inferSelect; + +//---------------**************---------------- + export const hooksTable = pgTable('hooks', { id: defaultUuidPkField(), title: varchar('title', { length: 40 }).notNull(), diff --git a/shared/schemas/review-tags.ts b/shared/schemas/review-tags.ts new file mode 100644 index 00000000..bb523569 --- /dev/null +++ b/shared/schemas/review-tags.ts @@ -0,0 +1,9 @@ +import { z } from 'zod'; + +export const reviewTagSchema = z.object({ + id: z.number().int().positive(), + title: z.string().max(8), + parent: z.number().int().min(0).max(4), +}); + +export type ReviewTag = z.infer;