Seth0330 commited on
Commit
cfbfed3
·
verified ·
1 Parent(s): 0ec6899

Update frontend/src/components/admin/AIInsightBox.jsx

Browse files
frontend/src/components/admin/AIInsightBox.jsx CHANGED
@@ -1,37 +1,89 @@
1
  // frontend/src/components/admin/AIInsightBox.jsx
2
  import React from "react";
 
 
3
 
4
- export default function AIInsightBox({ memberships }) {
5
- const total = memberships.length;
6
- const active = memberships.filter((m) => m.status === "active").length;
7
- const expired = memberships.filter((m) => m.status === "expired").length;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  return (
10
- <div className="mb-8 bg-white border border-stone-200 rounded-2xl p-4 sm:p-5 shadow-sm">
11
- <div className="flex flex-col sm:flex-row justify-between gap-3 sm:gap-4">
12
- <div>
13
- <h2 className="text-sm font-semibold text-stone-900">
14
- Quick membership insight
15
- </h2>
16
- <p className="text-xs text-stone-500 mt-1">
17
- This section will later be powered by the AI assistant, but for now
18
- it shows a quick snapshot of your dojo.
19
- </p>
20
- </div>
21
- <div className="flex flex-wrap gap-3 text-xs">
22
- <div className="px-3 py-2 rounded-lg bg-stone-50 border border-stone-200">
23
- <div className="text-stone-500">Total members</div>
24
- <div className="font-semibold text-stone-900">{total}</div>
 
 
 
 
25
  </div>
26
- <div className="px-3 py-2 rounded-lg bg-emerald-50 border border-emerald-100">
27
- <div className="text-emerald-700 text-[11px]">Active</div>
28
- <div className="font-semibold text-emerald-800">{active}</div>
 
 
 
 
 
 
 
 
 
29
  </div>
30
- <div className="px-3 py-2 rounded-lg bg-rose-50 border border-rose-100">
31
- <div className="text-rose-700 text-[11px]">Expired</div>
32
- <div className="font-semibold text-rose-800">{expired}</div>
 
 
 
 
 
 
 
 
 
33
  </div>
34
  </div>
 
 
 
 
 
 
 
35
  </div>
36
  </div>
37
  );
 
1
  // frontend/src/components/admin/AIInsightBox.jsx
2
  import React from "react";
3
+ import { Sparkles, TrendingUp, AlertTriangle, Users as UsersIcon } from "lucide-react";
4
+ import { differenceInDays } from "date-fns";
5
 
6
+ export default function AIInsightBox({ memberships = [] }) {
7
+ const now = new Date();
8
+
9
+ const totalMembers = memberships.length;
10
+
11
+ const renewingSoon = memberships.filter((m) => {
12
+ if (m.status !== "active" || !m.renewal_date) return false;
13
+ const days = differenceInDays(new Date(m.renewal_date), now);
14
+ return days >= 0 && days <= 14;
15
+ }).length;
16
+
17
+ const needAttention = memberships.filter((m) => {
18
+ if (!m.renewal_date) return false;
19
+ const days = differenceInDays(new Date(m.renewal_date), now);
20
+ return m.status === "expired" || days < 0;
21
+ }).length;
22
+
23
+ const goodStanding = memberships.filter((m) => m.status === "active").length;
24
+
25
+ const suggestionText =
26
+ totalMembers === 0
27
+ ? "Once members join, I’ll highlight who needs your attention first."
28
+ : `Focus on the ${needAttention} at-risk member${
29
+ needAttention === 1 ? "" : "s"
30
+ } this week to improve retention.`;
31
 
32
  return (
33
+ <div className="mb-8 rounded-3xl border border-purple-200 bg-gradient-to-r from-purple-50 to-purple-100/70 px-4 py-5 sm:px-6 sm:py-6">
34
+ <h2 className="text-sm font-semibold text-stone-900 mb-4 flex items-center gap-2">
35
+ <span className="inline-flex items-center justify-center h-6 w-6 rounded-full bg-purple-100 text-purple-700">
36
+ <Sparkles className="w-3 h-3" />
37
+ </span>
38
+ AI Assistant Insights
39
+ </h2>
40
+
41
+ <div className="space-y-3">
42
+ {/* Row 1 */}
43
+ <div className="flex items-center justify-between rounded-2xl bg-white/90 px-4 py-3 shadow-sm">
44
+ <div className="flex items-center gap-3">
45
+ <div className="h-8 w-8 rounded-full bg-emerald-50 flex items-center justify-center">
46
+ <TrendingUp className="w-4 h-4 text-emerald-600" />
47
+ </div>
48
+ <p className="text-sm text-stone-700">
49
+ {renewingSoon} member{renewingSoon === 1 ? "" : "s"} are due for
50
+ renewal in the next 2 weeks
51
+ </p>
52
  </div>
53
+ </div>
54
+
55
+ {/* Row 2 */}
56
+ <div className="flex items-center justify-between rounded-2xl bg-white/90 px-4 py-3 shadow-sm">
57
+ <div className="flex items-center gap-3">
58
+ <div className="h-8 w-8 rounded-full bg-amber-50 flex items-center justify-center">
59
+ <AlertTriangle className="w-4 h-4 text-amber-600" />
60
+ </div>
61
+ <p className="text-sm text-stone-700">
62
+ {needAttention} member{needAttention === 1 ? "" : "s"} need
63
+ immediate attention for renewal
64
+ </p>
65
  </div>
66
+ </div>
67
+
68
+ {/* Row 3 */}
69
+ <div className="flex items-center justify-between rounded-2xl bg-white/90 px-4 py-3 shadow-sm">
70
+ <div className="flex items-center gap-3">
71
+ <div className="h-8 w-8 rounded-full bg-blue-50 flex items-center justify-center">
72
+ <UsersIcon className="w-4 h-4 text-blue-600" />
73
+ </div>
74
+ <p className="text-sm text-stone-700">
75
+ {goodStanding} active member{goodStanding === 1 ? "" : "s"}{" "}
76
+ maintaining good standing
77
+ </p>
78
  </div>
79
  </div>
80
+
81
+ {/* Suggestion row */}
82
+ <div className="mt-3 rounded-2xl bg-purple-100 px-4 py-3">
83
+ <p className="text-sm text-purple-900">
84
+ <span className="font-semibold">Suggestion:</span> {suggestionText}
85
+ </p>
86
+ </div>
87
  </div>
88
  </div>
89
  );