import React, { useState } from "react"
import { TrendingUp, Edit2, Save, X } from "lucide-react"
const OKRDashboard = () => {
const [editingKR, setEditingKR] = useState(null)
const [editingTarget, setEditingTarget] = useState(null)
const [objectives, setObjectives] = useState([
{
id: 1,
title: "Spotify Listener Growth",
keyResults: [
{
id: 1,
description: "Monthly Listeners",
start: 4000,
current: 31000,
target: 25000,
unit: ""
},
{
id: 2,
description: "Active Listeners",
start: 1200,
current: 15000,
target: 10000,
unit: ""
},
{
id: 3,
description: "Playlist Adds",
start: 500,
current: 2800,
target: 2000,
unit: ""
},
{
id: 4,
description: "Popularity Score",
start: 12,
current: 25,
target: 20,
unit: "points"
}
]
},
{
id: 2,
title: "Instagram Community Growth",
keyResults: [
{
id: 5,
description: "Total Posts",
start: 0,
current: 32,
target: 48,
unit: "posts"
},
{
id: 6,
description: "Total Followers",
start: 3100,
current: 4100,
target: 4500,
unit: ""
},
{
id: 7,
description: "Avg Post Reach",
start: 1500,
current: 3500,
target: 5000,
unit: ""
},
{
id: 8,
description: "Avg Post Impressions",
start: 15000,
current: 28000,
target: 50000,
unit: ""
},
{
id: 9,
description: "Avg Engagement Rate",
start: 8,
current: 14,
target: 12,
unit: "%"
}
]
},
{
id: 3,
title: "TikTok Community Growth",
keyResults: [
{
id: 10,
description: "Total Posts",
start: 0,
current: 41,
target: 48,
unit: "posts"
},
{
id: 11,
description: "Total Followers",
start: 800,
current: 1800,
target: 2500,
unit: ""
},
{
id: 12,
description: "Watch Time (Per Video)",
start: 25,
current: 50,
target: 60,
unit: "%"
},
{
id: 13,
description: "Views (Per Video)",
start: 200,
current: 3000,
target: 2000,
unit: ""
},
{
id: 14,
description: "Likes (Per Video)",
start: 20,
current: 40,
target: 50,
unit: ""
}
]
},
{
id: 4,
title: "YouTube Community Growth",
keyResults: [
{
id: 15,
description: "Videos Released",
start: 0,
current: 4,
target: 6,
unit: "videos"
},
{
id: 16,
description: "Total Subscribers",
start: 800,
current: 1200,
target: 1500,
unit: ""
},
{
id: 17,
description: "Total Impressions",
start: 250000,
current: 2500000,
target: 1500000,
unit: ""
},
{
id: 18,
description: "Avg Watch Time",
start: 40,
current: 70,
target: 80,
unit: "%"
},
{
id: 19,
description: "Likes Per Video",
start: 100,
current: 250,
target: 400,
unit: ""
}
]
},
{
id: 5,
title: "Email Subscriber Growth",
keyResults: [
{
id: 20,
description: "Total Posts",
start: 0,
current: 20,
target: 24,
unit: "posts"
},
{
id: 21,
description: "Total Subscribers",
start: 100,
current: 1200,
target: 1000,
unit: ""
},
{
id: 22,
description: "Open Rate",
start: 12,
current: 32,
target: 40,
unit: "%"
},
{
id: 23,
description: "Click Through Rate",
start: 2,
current: 8,
target: 10,
unit: "%"
},
{
id: 24,
description: "Unsubscribe Rate",
start: 2,
current: 1,
target: 1,
unit: "%",
inverse: true
}
]
}
])
const calculateProgress = kr => {
const range = kr.target - kr.start
const current = kr.current - kr.start
if (kr.inverse) {
const inverseRange = kr.start - kr.target
const inverseProgress = kr.start - kr.current
if (inverseRange === 0) return 100
return Math.max(0, (inverseProgress / inverseRange) * 100)
}
if (range === 0) return 100
return Math.max(0, (current / range) * 100)
}
const calculateObjectiveProgress = objective => {
const avgProgress =
objective.keyResults.reduce((sum, kr) => sum + calculateProgress(kr), 0) /
objective.keyResults.length
return Math.round(avgProgress)
}
const formatValue = (value, unit) => {
if (unit === "%") return `${value}%`
if (value >= 1000000) return `${(value / 1000000).toFixed(1)}M`
if (value >= 1000) return `${(value / 1000).toFixed(0)}K`
return `${value}${unit ? " " + unit : ""}`
}
const updateKeyResult = (objId, krId, newValue) => {
setObjectives(
objectives.map(obj => {
if (obj.id === objId) {
return {
...obj,
keyResults: obj.keyResults.map(kr =>
kr.id === krId
? { ...kr, current: parseFloat(newValue) || 0 }
: kr
)
}
}
return obj
})
)
setEditingKR(null)
}
const updateTarget = (objId, krId, newValue) => {
setObjectives(
objectives.map(obj => {
if (obj.id === objId) {
return {
...obj,
keyResults: obj.keyResults.map(kr =>
kr.id === krId ? { ...kr, target: parseFloat(newValue) || 0 } : kr
)
}
}
return obj
})
)
setEditingTarget(null)
}
const getProgressColor = progress => {
if (progress >= 80) return "bg-green-500"
if (progress >= 50) return "bg-yellow-500"
return "bg-red-500"
}
const getStatusBadge = progress => {
if (progress >= 100) {
return (
Strong Progress
)
}
export default OKRDashboard
Completed
)
} else if (progress >= 50) {
return (
On Track
)
} else {
return (
Behind
)
}
}
return (
LONESOME JOY
Campaign Performance
Average progress across all growth objectives
{Math.round(
objectives.reduce(
(sum, obj) => sum + calculateObjectiveProgress(obj),
0
) / objectives.length
)}
%
Cycle:
6 Months
Start Date:
January 1, 2025
End Date:
June 30, 2025
Time Elapsed:
100%
{objectives.map(objective => {
const objProgress = calculateObjectiveProgress(objective)
return (
)
})}
{objective.title}
{objProgress}%
{objective.keyResults.map(kr => {
const progress = calculateProgress(kr)
const isEditing = editingKR === `${objective.id}-${kr.id}`
const isEditingTarget =
editingTarget === `${objective.id}-${kr.id}`
return (
)
})}
{Math.round(progress)}%
{kr.description}
Start:
{formatValue(kr.start, kr.unit)}
→
{isEditing ? (
Current:
{
if (e.key === "Enter") {
updateKeyResult(
objective.id,
kr.id,
e.target.value
)
}
}}
autoFocus
id={`input-${kr.id}`}
/>
) : (
Current:
{formatValue(kr.current, kr.unit)}
)}
→
{isEditingTarget ? (
Target:
{
if (e.key === "Enter") {
updateTarget(
objective.id,
kr.id,
e.target.value
)
}
}}
autoFocus
id={`target-${kr.id}`}
/>
) : (
Target:
{formatValue(kr.target, kr.unit)}
)}
{getStatusBadge(progress)}