feat: introduce Teams & OKRs feature with models, types, and UI components for team management and objective tracking
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 12m53s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 12m53s
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
-- CreateEnum
|
||||
CREATE TABLE "TeamRole" (
|
||||
"value" TEXT NOT NULL PRIMARY KEY
|
||||
);
|
||||
INSERT INTO "TeamRole" ("value") VALUES ('ADMIN'), ('MEMBER');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TABLE "OKRStatus" (
|
||||
"value" TEXT NOT NULL PRIMARY KEY
|
||||
);
|
||||
INSERT INTO "OKRStatus" ("value") VALUES ('NOT_STARTED'), ('IN_PROGRESS'), ('COMPLETED'), ('CANCELLED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TABLE "KeyResultStatus" (
|
||||
"value" TEXT NOT NULL PRIMARY KEY
|
||||
);
|
||||
INSERT INTO "KeyResultStatus" ("value") VALUES ('NOT_STARTED'), ('IN_PROGRESS'), ('COMPLETED'), ('AT_RISK');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Team" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"createdById" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "Team_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "TeamMember" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"teamId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"role" TEXT NOT NULL DEFAULT 'MEMBER',
|
||||
"joinedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "TeamMember_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT "TeamMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "OKR" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"teamMemberId" TEXT NOT NULL,
|
||||
"objective" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"period" TEXT NOT NULL,
|
||||
"startDate" DATETIME NOT NULL,
|
||||
"endDate" DATETIME NOT NULL,
|
||||
"status" TEXT NOT NULL DEFAULT 'NOT_STARTED',
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "OKR_teamMemberId_fkey" FOREIGN KEY ("teamMemberId") REFERENCES "TeamMember" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "KeyResult" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"okrId" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"targetValue" REAL NOT NULL,
|
||||
"currentValue" REAL NOT NULL DEFAULT 0,
|
||||
"unit" TEXT NOT NULL DEFAULT '%',
|
||||
"status" TEXT NOT NULL DEFAULT 'NOT_STARTED',
|
||||
"order" INTEGER NOT NULL DEFAULT 0,
|
||||
"notes" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "KeyResult_okrId_fkey" FOREIGN KEY ("okrId") REFERENCES "OKR" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Team_createdById_idx" ON "Team"("createdById");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TeamMember_teamId_idx" ON "TeamMember"("teamId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TeamMember_userId_idx" ON "TeamMember"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "TeamMember_teamId_userId_key" ON "TeamMember"("teamId", "userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "OKR_teamMemberId_idx" ON "OKR"("teamMemberId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "OKR_teamMemberId_period_idx" ON "OKR"("teamMemberId", "period");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "OKR_status_idx" ON "OKR"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "KeyResult_okrId_idx" ON "KeyResult"("okrId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "KeyResult_okrId_order_idx" ON "KeyResult"("okrId", "order");
|
||||
|
||||
@@ -25,6 +25,9 @@ model User {
|
||||
yearReviewSessions YearReviewSession[]
|
||||
sharedYearReviewSessions YRSessionShare[]
|
||||
yearReviewSessionEvents YRSessionEvent[]
|
||||
// Teams & OKRs relations
|
||||
createdTeams Team[]
|
||||
teamMembers TeamMember[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
@@ -274,3 +277,91 @@ model YRSessionEvent {
|
||||
|
||||
@@index([sessionId, createdAt])
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Teams & OKRs
|
||||
// ============================================
|
||||
|
||||
enum TeamRole {
|
||||
ADMIN
|
||||
MEMBER
|
||||
}
|
||||
|
||||
enum OKRStatus {
|
||||
NOT_STARTED
|
||||
IN_PROGRESS
|
||||
COMPLETED
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
enum KeyResultStatus {
|
||||
NOT_STARTED
|
||||
IN_PROGRESS
|
||||
COMPLETED
|
||||
AT_RISK
|
||||
}
|
||||
|
||||
model Team {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
description String?
|
||||
createdById String
|
||||
creator User @relation(fields: [createdById], references: [id], onDelete: Cascade)
|
||||
members TeamMember[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([createdById])
|
||||
}
|
||||
|
||||
model TeamMember {
|
||||
id String @id @default(cuid())
|
||||
teamId String
|
||||
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
role TeamRole @default(MEMBER)
|
||||
okrs OKR[]
|
||||
joinedAt DateTime @default(now())
|
||||
|
||||
@@unique([teamId, userId])
|
||||
@@index([teamId])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model OKR {
|
||||
id String @id @default(cuid())
|
||||
teamMemberId String
|
||||
teamMember TeamMember @relation(fields: [teamMemberId], references: [id], onDelete: Cascade)
|
||||
objective String
|
||||
description String?
|
||||
period String // Q1 2025, Q2 2025, H1 2025, 2025, etc.
|
||||
startDate DateTime
|
||||
endDate DateTime
|
||||
status OKRStatus @default(NOT_STARTED)
|
||||
keyResults KeyResult[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([teamMemberId])
|
||||
@@index([teamMemberId, period])
|
||||
@@index([status])
|
||||
}
|
||||
|
||||
model KeyResult {
|
||||
id String @id @default(cuid())
|
||||
okrId String
|
||||
okr OKR @relation(fields: [okrId], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
targetValue Float
|
||||
currentValue Float @default(0)
|
||||
unit String @default("%") // %, nombre, etc.
|
||||
status KeyResultStatus @default(NOT_STARTED)
|
||||
order Int @default(0)
|
||||
notes String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([okrId])
|
||||
@@index([okrId, order])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user