forked from MyPeerformance/peerformance-my-account
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNew_StudyDetails.js
More file actions
153 lines (145 loc) · 6.65 KB
/
Copy pathNew_StudyDetails.js
File metadata and controls
153 lines (145 loc) · 6.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import React, { useState } from "react";
import { ChevronDown } from "lucide-react";
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
const studies = [
{
name: "PT revenue per member",
status: "Available",
renewalDate: "01/07/2025",
participants: 5,
peerGroup: "UK PTs, 10-50 employees",
region: "London, UK",
description: "Benchmark PT revenue per member against similar-sized UK businesses.",
dataHistory: ["Jan: Submitted", "Feb: Submitted", "Mar: Missing"],
},
{
name: "Monthly spend on marketing",
status: "Queued",
renewalDate: null,
participants: 3,
peerGroup: "UK Gyms, 10-100 employees",
region: "Manchester, UK",
description: "Track monthly marketing expenditure and impact.",
dataHistory: ["Jan: Submitted", "Feb: Missing", "Mar: Missing"],
},
{
name: "New member acquisition rate",
status: "Available",
renewalDate: "01/07/2025",
participants: 7,
peerGroup: "Fitness Studios, National",
region: "UK Wide",
description: "Measure how fast you grow your new member base each month.",
dataHistory: ["Jan: Submitted", "Feb: Submitted", "Mar: Submitted"],
},
{
name: "Member referral rate",
status: "Available",
renewalDate: "30/04/2025",
participants: 5,
peerGroup: "Boutique Fitness, Urban",
region: "Bristol, UK",
description: "How often your members refer others to your business.",
dataHistory: ["Jan: Missing", "Feb: Submitted", "Mar: Missing"],
},
];
const statusText = (status) => {
const colors = {
Available: "text-green-400",
Queued: "text-yellow-400",
Inactive: "text-red-400",
};
return <span className={`text-sm font-medium ${colors[status] || "text-gray-400"}`}>{status}</span>;
};
const formatDataEntry = (entry) => {
const isMissing = entry.includes("Missing");
const color = isMissing ? "text-red-400" : "text-green-400";
return <div className={`text-sm ${color}`}>• {entry}</div>;
};
export default function StudyDetailsTable() {
const [expandedRow, setExpandedRow] = useState(null);
const [sortColumn, setSortColumn] = useState("name");
const [sortAsc, setSortAsc] = useState(true);
const [modalStudy, setModalStudy] = useState(null);
const sortedStudies = [...studies].sort((a, b) => {
const aVal = a[sortColumn] || "";
const bVal = b[sortColumn] || "";
if (typeof aVal === "string") {
return sortAsc ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
}
return sortAsc ? aVal - bVal : bVal - aVal;
});
return (
<div className="bg-[#0f172a] min-h-screen text-white p-10">
<div className="max-w-6xl mx-auto space-y-6">
<h1 className="text-2xl font-semibold">Your Studies</h1>
<div className="overflow-x-auto rounded-xl border border-gray-700">
<table className="min-w-full divide-y divide-gray-700 text-sm">
<thead className="bg-gray-900">
<tr>
<th className="px-6 py-3 text-left font-medium text-gray-300 cursor-pointer" onClick={() => { setSortColumn("name"); setSortAsc(sortColumn === "name" ? !sortAsc : true); }}>Study Name</th>
<th className="px-6 py-3 text-left font-medium text-gray-300 cursor-pointer" onClick={() => { setSortColumn("status"); setSortAsc(sortColumn === "status" ? !sortAsc : true); }}>Status</th>
<th className="px-6 py-3 text-left font-medium text-gray-300 cursor-pointer" onClick={() => { setSortColumn("renewalDate"); setSortAsc(sortColumn === "renewalDate" ? !sortAsc : true); }}>Renewal Date</th>
<th className="px-6 py-3 text-left font-medium text-gray-300 cursor-pointer" onClick={() => { setSortColumn("participants"); setSortAsc(sortColumn === "participants" ? !sortAsc : true); }}>Participants</th>
<th className="px-6 py-3 text-left font-medium text-gray-300">Data</th>
</tr>
</thead>
<tbody className="bg-[#1e293b] divide-y divide-gray-800">
{sortedStudies.map((study, idx) => (
<React.Fragment key={idx}>
<tr>
<td
className="px-6 py-4 whitespace-nowrap text-blue-400 hover:underline cursor-pointer"
onClick={() => setModalStudy(study)}
>
{study.name}
</td>
<td className="px-6 py-4 whitespace-nowrap">{statusText(study.status)}</td>
<td className="px-6 py-4 whitespace-nowrap text-white">{study.renewalDate || "—"}</td>
<td className="px-6 py-4 whitespace-nowrap text-white">{study.participants}</td>
<td className="px-6 py-4 whitespace-nowrap">
{study.status !== "Queued" && (
<button
className="flex items-center space-x-1 text-blue-400 hover:underline"
onClick={() =>
setExpandedRow(expandedRow === idx ? null : idx)
}
>
<ChevronDown className={`w-4 h-4 transition-transform ${expandedRow === idx ? "rotate-180" : "rotate-0"}`} />
<span>View</span>
</button>
)}
</td>
</tr>
{expandedRow === idx && study.status !== "Queued" && (
<tr>
<td colSpan="5" className="px-6 py-4 bg-gray-900">
<div className="text-sm text-gray-300 space-y-1">
{study.dataHistory.map((entry, i) => (
<div key={i}>{formatDataEntry(entry)}</div>
))}
</div>
</td>
</tr>
)}
</React.Fragment>
))}
</tbody>
</table>
</div>
{modalStudy && (
<Dialog open={true} onOpenChange={() => setModalStudy(null)}>
<DialogContent className="bg-[#111827] border border-gray-700 text-white rounded-2xl max-w-md mx-auto p-6">
<DialogTitle className="text-xl font-semibold mb-2">{modalStudy.name}</DialogTitle>
<p className="text-sm text-gray-400 mb-4">{modalStudy.description}</p>
<div className="text-sm space-y-2">
<p><span className="text-gray-400">Peer Group:</span> {modalStudy.peerGroup}</p>
<p><span className="text-gray-400">Region:</span> {modalStudy.region}</p>
</div>
</DialogContent>
</Dialog>
)}
</div>
</div>
);
}