實作部門分析數據
This commit is contained in:
@@ -57,153 +57,25 @@ function AnalyticsContent() {
|
||||
totalTests: 0,
|
||||
})
|
||||
|
||||
const departments = ["人力資源部", "資訊技術部", "財務部", "行銷部", "業務部", "研發部", "客服部", "其他"]
|
||||
|
||||
useEffect(() => {
|
||||
loadAnalyticsData()
|
||||
}, [])
|
||||
|
||||
const loadAnalyticsData = () => {
|
||||
// Load users
|
||||
const users: User[] = JSON.parse(localStorage.getItem("hr_users") || "[]")
|
||||
const loadAnalyticsData = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/admin/analytics/departments')
|
||||
const data = await response.json()
|
||||
|
||||
// Load all test results
|
||||
const allResults: TestResult[] = []
|
||||
|
||||
users.forEach((user: User) => {
|
||||
// Check for logic test results
|
||||
const logicKey = `logicTestResults_${user.id}`
|
||||
const logicResults = localStorage.getItem(logicKey)
|
||||
if (logicResults) {
|
||||
const data = JSON.parse(logicResults)
|
||||
allResults.push({
|
||||
userId: user.id,
|
||||
userName: user.name,
|
||||
userDepartment: user.department,
|
||||
type: "logic",
|
||||
score: data.score,
|
||||
completedAt: data.completedAt,
|
||||
})
|
||||
if (data.success) {
|
||||
setDepartmentStats(data.data.departmentStats)
|
||||
setOverallStats(data.data.overallStats)
|
||||
} else {
|
||||
console.error('獲取部門分析數據失敗:', data.message)
|
||||
}
|
||||
|
||||
// Check for creative test results
|
||||
const creativeKey = `creativeTestResults_${user.id}`
|
||||
const creativeResults = localStorage.getItem(creativeKey)
|
||||
if (creativeResults) {
|
||||
const data = JSON.parse(creativeResults)
|
||||
allResults.push({
|
||||
userId: user.id,
|
||||
userName: user.name,
|
||||
userDepartment: user.department,
|
||||
type: "creative",
|
||||
score: data.score,
|
||||
completedAt: data.completedAt,
|
||||
})
|
||||
}
|
||||
|
||||
// Check for combined test results
|
||||
const combinedKey = `combinedTestResults_${user.id}`
|
||||
const combinedResults = localStorage.getItem(combinedKey)
|
||||
if (combinedResults) {
|
||||
const data = JSON.parse(combinedResults)
|
||||
allResults.push({
|
||||
userId: user.id,
|
||||
userName: user.name,
|
||||
userDepartment: user.department,
|
||||
type: "combined",
|
||||
score: data.overallScore,
|
||||
completedAt: data.completedAt,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Calculate department statistics
|
||||
const deptStats: DepartmentStats[] = departments
|
||||
.map((dept) => {
|
||||
const deptUsers = users.filter((u) => u.department === dept)
|
||||
const deptResults = allResults.filter((r) => r.userDepartment === dept)
|
||||
const participatedUsers = new Set(deptResults.map((r) => r.userId)).size
|
||||
|
||||
// Calculate average scores by test type
|
||||
const logicResults = deptResults.filter((r) => r.type === "logic")
|
||||
const creativeResults = deptResults.filter((r) => r.type === "creative")
|
||||
const combinedResults = deptResults.filter((r) => r.type === "combined")
|
||||
|
||||
const averageLogicScore =
|
||||
logicResults.length > 0
|
||||
? Math.round(logicResults.reduce((sum, r) => sum + r.score, 0) / logicResults.length)
|
||||
: 0
|
||||
|
||||
const averageCreativeScore =
|
||||
creativeResults.length > 0
|
||||
? Math.round(creativeResults.reduce((sum, r) => sum + r.score, 0) / creativeResults.length)
|
||||
: 0
|
||||
|
||||
const averageCombinedScore =
|
||||
combinedResults.length > 0
|
||||
? Math.round(combinedResults.reduce((sum, r) => sum + r.score, 0) / combinedResults.length)
|
||||
: 0
|
||||
|
||||
// Calculate overall average
|
||||
const allScores = [averageLogicScore, averageCreativeScore, averageCombinedScore].filter((s) => s > 0)
|
||||
const overallAverage =
|
||||
allScores.length > 0 ? Math.round(allScores.reduce((sum, s) => sum + s, 0) / allScores.length) : 0
|
||||
|
||||
// Find top performer
|
||||
const userScores = new Map<string, number[]>()
|
||||
deptResults.forEach((result) => {
|
||||
if (!userScores.has(result.userId)) {
|
||||
userScores.set(result.userId, [])
|
||||
}
|
||||
userScores.get(result.userId)!.push(result.score)
|
||||
})
|
||||
|
||||
let topPerformer: string | null = null
|
||||
let topScore = 0
|
||||
userScores.forEach((scores, userId) => {
|
||||
const avgScore = scores.reduce((sum, s) => sum + s, 0) / scores.length
|
||||
if (avgScore > topScore) {
|
||||
topScore = avgScore
|
||||
const user = users.find((u) => u.id === userId)
|
||||
topPerformer = user ? user.name : null
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
department: dept,
|
||||
totalUsers: deptUsers.length,
|
||||
participatedUsers,
|
||||
participationRate: deptUsers.length > 0 ? Math.round((participatedUsers / deptUsers.length) * 100) : 0,
|
||||
averageLogicScore,
|
||||
averageCreativeScore,
|
||||
averageCombinedScore,
|
||||
overallAverage,
|
||||
topPerformer,
|
||||
testCounts: {
|
||||
logic: logicResults.length,
|
||||
creative: creativeResults.length,
|
||||
combined: combinedResults.length,
|
||||
},
|
||||
}
|
||||
})
|
||||
.filter((stat) => stat.totalUsers > 0) // Only show departments with users
|
||||
|
||||
setDepartmentStats(deptStats)
|
||||
|
||||
// Calculate overall statistics
|
||||
const totalUsers = users.length
|
||||
const totalParticipants = new Set(allResults.map((r) => r.userId)).size
|
||||
const overallParticipationRate = totalUsers > 0 ? Math.round((totalParticipants / totalUsers) * 100) : 0
|
||||
const averageScore =
|
||||
allResults.length > 0 ? Math.round(allResults.reduce((sum, r) => sum + r.score, 0) / allResults.length) : 0
|
||||
|
||||
setOverallStats({
|
||||
totalUsers,
|
||||
totalParticipants,
|
||||
overallParticipationRate,
|
||||
averageScore,
|
||||
totalTests: allResults.length,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('獲取部門分析數據錯誤:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const getScoreColor = (score: number) => {
|
||||
@@ -314,9 +186,9 @@ function AnalyticsContent() {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">所有部門</SelectItem>
|
||||
{departments.map((dept) => (
|
||||
<SelectItem key={dept} value={dept}>
|
||||
{dept}
|
||||
{departmentStats.map((stat) => (
|
||||
<SelectItem key={stat.department} value={stat.department}>
|
||||
{stat.department}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
|
Reference in New Issue
Block a user