@schandlergarcia/sf-web-components 2.3.9 → 2.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.3.10] - 2026-04-13
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Metric numbers now big in both themes** — `--dash-metric-size` is `3.25rem` in both neutral and Engine (no longer starts small). Subtitles bumped from `text-xs` to `text-sm` for readability.
|
|
12
|
+
- **Badges stay fixed size** — removed per-theme badge sizing; instead Engine uses brighter semantic colors (`--dash-success: #34d399`, `--dash-info: #67e8f9`) so status chips pop more.
|
|
13
|
+
- **Billing & Contract moved above Recent Activity** — section reorder puts revenue charts, invoices, and contract details higher in the page flow.
|
|
14
|
+
- **Two charts side by side** — added "Total revenue growth" bar chart next to the existing "Revenue by property" multi-line chart. Bar chart computes monthly totals from live property data and uses the theme accent color, showing clear upward growth.
|
|
15
|
+
|
|
8
16
|
## [2.3.9] - 2026-04-13
|
|
9
17
|
|
|
10
18
|
### Changed
|
|
@@ -662,6 +662,63 @@ export default function PartnerHubDashboard() {
|
|
|
662
662
|
.style("fill", "currentColor");
|
|
663
663
|
}, []);
|
|
664
664
|
|
|
665
|
+
const monthlyTotalRevenue = React.useMemo(() => {
|
|
666
|
+
if (!revenueTrendByProperty?.months || !revenueTrendByProperty?.properties) return null;
|
|
667
|
+
return revenueTrendByProperty.months.map((month: string, i: number) => ({
|
|
668
|
+
month,
|
|
669
|
+
total: revenueTrendByProperty.properties.reduce((sum: number, p: any) => sum + p.values[i], 0),
|
|
670
|
+
}));
|
|
671
|
+
}, [revenueTrendByProperty]);
|
|
672
|
+
|
|
673
|
+
const renderTotalRevenueGrowth = React.useCallback((svgEl: any, data: any, { width, height }: any) => {
|
|
674
|
+
if (!data || !data.length) return;
|
|
675
|
+
const margin = { top: 20, right: 20, bottom: 40, left: 70 };
|
|
676
|
+
const innerWidth = width - margin.left - margin.right;
|
|
677
|
+
const innerHeight = height - margin.top - margin.bottom;
|
|
678
|
+
if (innerWidth <= 0 || innerHeight <= 0) return;
|
|
679
|
+
|
|
680
|
+
const svg = d3.select(svgEl);
|
|
681
|
+
svg.selectAll("*").remove();
|
|
682
|
+
const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
|
|
683
|
+
|
|
684
|
+
const x = d3.scaleBand().domain(data.map((d: any) => d.month)).range([0, innerWidth]).padding(0.35);
|
|
685
|
+
const maxVal = d3.max(data, (d: any) => d.total) || 0;
|
|
686
|
+
const y = d3.scaleLinear().domain([0, maxVal * 1.15]).range([innerHeight, 0]).nice();
|
|
687
|
+
|
|
688
|
+
g.append("g").attr("class", "grid")
|
|
689
|
+
.call(d3.axisLeft(y).ticks(5).tickSize(-innerWidth).tickFormat(() => ""))
|
|
690
|
+
.selectAll("line").style("stroke", "currentColor").style("stroke-opacity", "0.08");
|
|
691
|
+
g.select(".grid .domain").remove();
|
|
692
|
+
|
|
693
|
+
const accentColor = getComputedStyle(document.documentElement).getPropertyValue('--dash-accent').trim() || '#2563eb';
|
|
694
|
+
|
|
695
|
+
g.selectAll(".bar").data(data).join("rect")
|
|
696
|
+
.attr("x", (d: any) => x(d.month) ?? 0)
|
|
697
|
+
.attr("y", (d: any) => y(d.total))
|
|
698
|
+
.attr("width", x.bandwidth())
|
|
699
|
+
.attr("height", (d: any) => innerHeight - y(d.total))
|
|
700
|
+
.attr("rx", 4)
|
|
701
|
+
.attr("fill", accentColor)
|
|
702
|
+
.attr("fill-opacity", 0.85);
|
|
703
|
+
|
|
704
|
+
g.selectAll(".label").data(data).join("text")
|
|
705
|
+
.attr("x", (d: any) => (x(d.month) ?? 0) + x.bandwidth() / 2)
|
|
706
|
+
.attr("y", (d: any) => y(d.total) - 8)
|
|
707
|
+
.attr("text-anchor", "middle")
|
|
708
|
+
.style("font-size", "11px")
|
|
709
|
+
.style("font-weight", "600")
|
|
710
|
+
.style("fill", "currentColor")
|
|
711
|
+
.text((d: any) => `$${(d.total / 1000).toFixed(0)}K`);
|
|
712
|
+
|
|
713
|
+
g.append("g").attr("transform", `translate(0,${innerHeight})`)
|
|
714
|
+
.call(d3.axisBottom(x)).selectAll("text")
|
|
715
|
+
.style("font-size", "11px").style("fill", "currentColor").attr("dy", "1.2em");
|
|
716
|
+
g.select(".domain").style("stroke-opacity", "0.2");
|
|
717
|
+
|
|
718
|
+
g.append("g").call(d3.axisLeft(y).ticks(5).tickFormat(d3.format("$~s")))
|
|
719
|
+
.selectAll("text").style("font-size", "11px").style("fill", "currentColor");
|
|
720
|
+
}, []);
|
|
721
|
+
|
|
665
722
|
return (
|
|
666
723
|
<div className="heroui-scope min-h-screen bg-[var(--color-dash-surface)] dark:bg-[var(--color-dash-text)] transition-colors duration-300">
|
|
667
724
|
{/* Header - Refined Engine Brand */}
|
|
@@ -801,13 +858,13 @@ export default function PartnerHubDashboard() {
|
|
|
801
858
|
<div className="bg-[var(--color-dash-success)]/10 rounded-lg p-2">
|
|
802
859
|
<BanknotesIcon className="h-5 w-5 text-[var(--color-dash-success)]" />
|
|
803
860
|
</div>
|
|
804
|
-
<span className="inline-flex items-center rounded-full font-bold bg-[var(--color-dash-success)]/10 text-[var(--color-dash-success)]"
|
|
861
|
+
<span className="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-bold bg-[var(--color-dash-success)]/10 text-[var(--color-dash-success)]">
|
|
805
862
|
+45%
|
|
806
863
|
</span>
|
|
807
864
|
</div>
|
|
808
|
-
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-
|
|
865
|
+
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-sm font-semibold mb-2 uppercase tracking-wider">Total Revenue</p>
|
|
809
866
|
<p className="font-black text-[var(--color-dash-text)] dark:text-white mb-1 leading-tight" style={{ fontSize: 'var(--dash-metric-size)' }}>${(myRevenue / 1000).toFixed(0)}K</p>
|
|
810
|
-
<p className="text-
|
|
867
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">earned with Engine</p>
|
|
811
868
|
</>
|
|
812
869
|
)}
|
|
813
870
|
</div>
|
|
@@ -827,13 +884,13 @@ export default function PartnerHubDashboard() {
|
|
|
827
884
|
<div className="bg-[var(--color-dash-warning)]/10 rounded-lg p-2">
|
|
828
885
|
<ExclamationTriangleIcon className="h-5 w-5 text-[var(--color-dash-warning)]" />
|
|
829
886
|
</div>
|
|
830
|
-
<span className="inline-flex items-center rounded-full font-bold bg-[var(--color-dash-warning)] text-white"
|
|
887
|
+
<span className="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-bold bg-[var(--color-dash-warning)] text-white">
|
|
831
888
|
REVIEW
|
|
832
889
|
</span>
|
|
833
890
|
</div>
|
|
834
|
-
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-
|
|
891
|
+
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-sm font-semibold mb-2 uppercase tracking-wider">Things to Review</p>
|
|
835
892
|
<p className="font-black text-[var(--color-dash-text)] dark:text-white mb-1 leading-tight" style={{ fontSize: 'var(--dash-metric-size)' }}>{myOpenDisputes}</p>
|
|
836
|
-
<p className="text-
|
|
893
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">items need attention</p>
|
|
837
894
|
</>
|
|
838
895
|
)}
|
|
839
896
|
</div>
|
|
@@ -854,9 +911,9 @@ export default function PartnerHubDashboard() {
|
|
|
854
911
|
<BuildingOfficeIcon className="h-5 w-5 text-[var(--color-dash-accent)]" />
|
|
855
912
|
</div>
|
|
856
913
|
</div>
|
|
857
|
-
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-
|
|
914
|
+
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-sm font-semibold mb-2 uppercase tracking-wider">Properties</p>
|
|
858
915
|
<p className="font-black text-[var(--color-dash-text)] dark:text-white mb-1 leading-tight" style={{ fontSize: 'var(--dash-metric-size)' }}>{myProperties}</p>
|
|
859
|
-
<p className="text-
|
|
916
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">active locations</p>
|
|
860
917
|
</>
|
|
861
918
|
)}
|
|
862
919
|
</div>
|
|
@@ -877,9 +934,9 @@ export default function PartnerHubDashboard() {
|
|
|
877
934
|
<ClockIcon className="h-5 w-5 text-[var(--color-dash-info)]" />
|
|
878
935
|
</div>
|
|
879
936
|
</div>
|
|
880
|
-
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-
|
|
937
|
+
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-sm font-semibold mb-2 uppercase tracking-wider">Reservations</p>
|
|
881
938
|
<p className="font-black text-[var(--color-dash-text)] dark:text-white mb-1 leading-tight" style={{ fontSize: 'var(--dash-metric-size)' }}>{myReservations}</p>
|
|
882
|
-
<p className="text-
|
|
939
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">through Engine</p>
|
|
883
940
|
</>
|
|
884
941
|
)}
|
|
885
942
|
</div>
|
|
@@ -900,9 +957,9 @@ export default function PartnerHubDashboard() {
|
|
|
900
957
|
<ShieldCheckIcon className="h-5 w-5 text-[var(--color-dash-danger)]" />
|
|
901
958
|
</div>
|
|
902
959
|
</div>
|
|
903
|
-
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-
|
|
960
|
+
<p className="text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] text-sm font-semibold mb-2 uppercase tracking-wider">Invoices</p>
|
|
904
961
|
<p className="font-black text-[var(--color-dash-text)] dark:text-white mb-1 leading-tight" style={{ fontSize: 'var(--dash-metric-size)' }}>{myPendingInvoices}</p>
|
|
905
|
-
<p className="text-
|
|
962
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">ready to pay</p>
|
|
906
963
|
</>
|
|
907
964
|
)}
|
|
908
965
|
</div>
|
|
@@ -977,7 +1034,7 @@ export default function PartnerHubDashboard() {
|
|
|
977
1034
|
<h3 className="text-xl font-bold text-[var(--color-dash-text)] dark:text-white">
|
|
978
1035
|
{property.name}
|
|
979
1036
|
</h3>
|
|
980
|
-
<span className="inline-flex items-center rounded-full font-bold bg-[var(--color-dash-success)]/20 text-[var(--color-dash-success)] border border-[var(--color-dash-success)]/30"
|
|
1037
|
+
<span className="inline-flex items-center rounded-full px-3 py-1 text-xs font-bold bg-[var(--color-dash-success)]/20 text-[var(--color-dash-success)] border border-[var(--color-dash-success)]/30">
|
|
981
1038
|
+{property.growth}% growth
|
|
982
1039
|
</span>
|
|
983
1040
|
</div>
|
|
@@ -1044,7 +1101,7 @@ export default function PartnerHubDashboard() {
|
|
|
1044
1101
|
ATR-00001 · Summit Austin Convention Center · TechCorp Inc. booking
|
|
1045
1102
|
</p>
|
|
1046
1103
|
</div>
|
|
1047
|
-
<span className="inline-flex items-center rounded-full font-bold bg-[var(--color-dash-warning)] text-white flex-shrink-0"
|
|
1104
|
+
<span className="inline-flex items-center rounded-full px-3 py-1 text-xs font-bold bg-[var(--color-dash-warning)] text-white flex-shrink-0">
|
|
1048
1105
|
NEEDS REVIEW
|
|
1049
1106
|
</span>
|
|
1050
1107
|
</div>
|
|
@@ -1092,7 +1149,164 @@ export default function PartnerHubDashboard() {
|
|
|
1092
1149
|
</div>
|
|
1093
1150
|
)}
|
|
1094
1151
|
|
|
1095
|
-
{/* Section
|
|
1152
|
+
{/* Section — Billing & Contract Details */}
|
|
1153
|
+
<div className="pt-8 space-y-2">
|
|
1154
|
+
<h2 className="text-3xl font-bold text-[var(--color-dash-text)] dark:text-white tracking-tight">
|
|
1155
|
+
Billing & contract details
|
|
1156
|
+
</h2>
|
|
1157
|
+
<p className="text-lg text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1158
|
+
Keep track of invoices and your partnership terms
|
|
1159
|
+
</p>
|
|
1160
|
+
</div>
|
|
1161
|
+
|
|
1162
|
+
{/* Two Charts Grid */}
|
|
1163
|
+
{isLoading ? (
|
|
1164
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
1165
|
+
<CardSkeleton lines={6} />
|
|
1166
|
+
<CardSkeleton lines={6} />
|
|
1167
|
+
</div>
|
|
1168
|
+
) : (
|
|
1169
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
1170
|
+
{/* Revenue Trend by Property (multi-line) */}
|
|
1171
|
+
<div className="bg-white dark:bg-[var(--color-dash-text)] border border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30 rounded-xl shadow-sm hover:shadow-lg transition-shadow duration-300 overflow-hidden">
|
|
1172
|
+
<div className="p-6 border-b border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
|
|
1173
|
+
<h3 className="text-xl font-bold text-[var(--color-dash-text)] dark:text-white mb-1">
|
|
1174
|
+
Revenue by property
|
|
1175
|
+
</h3>
|
|
1176
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1177
|
+
Monthly trend across {revenueTrendByProperty.properties?.length || 4} properties
|
|
1178
|
+
</p>
|
|
1179
|
+
<div className="flex flex-wrap gap-3 mt-3">
|
|
1180
|
+
{revenueTrendByProperty.properties.map((prop) => (
|
|
1181
|
+
<div key={prop.name} className="flex items-center gap-1.5">
|
|
1182
|
+
<span className="inline-block h-2 w-2 rounded-full flex-shrink-0" style={{ backgroundColor: prop.color }} />
|
|
1183
|
+
<span className="text-xs font-medium text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">{prop.name.replace('Summit ', '')}</span>
|
|
1184
|
+
</div>
|
|
1185
|
+
))}
|
|
1186
|
+
</div>
|
|
1187
|
+
</div>
|
|
1188
|
+
<div className="p-4 w-full">
|
|
1189
|
+
{revenueTrendByProperty?.months && revenueTrendByProperty?.properties ? (
|
|
1190
|
+
<div className="w-full" style={{ minHeight: '240px' }}>
|
|
1191
|
+
<D3Chart data={revenueTrendByProperty} renderChart={renderRevenueTrendByProperty} height={240} responsive={true} ariaLabel="Revenue trend by property" />
|
|
1192
|
+
</div>
|
|
1193
|
+
) : (
|
|
1194
|
+
<div className="h-[240px] flex items-center justify-center text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">Loading chart data...</div>
|
|
1195
|
+
)}
|
|
1196
|
+
</div>
|
|
1197
|
+
</div>
|
|
1198
|
+
|
|
1199
|
+
{/* Total Monthly Revenue Growth (bar chart) */}
|
|
1200
|
+
<div className="bg-white dark:bg-[var(--color-dash-text)] border border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30 rounded-xl shadow-sm hover:shadow-lg transition-shadow duration-300 overflow-hidden">
|
|
1201
|
+
<div className="p-6 border-b border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
|
|
1202
|
+
<h3 className="text-xl font-bold text-[var(--color-dash-text)] dark:text-white mb-1">
|
|
1203
|
+
Total revenue growth
|
|
1204
|
+
</h3>
|
|
1205
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1206
|
+
Combined monthly revenue — up 67% over 6 months
|
|
1207
|
+
</p>
|
|
1208
|
+
</div>
|
|
1209
|
+
<div className="p-4 w-full">
|
|
1210
|
+
{monthlyTotalRevenue ? (
|
|
1211
|
+
<div className="w-full" style={{ minHeight: '240px' }}>
|
|
1212
|
+
<D3Chart data={monthlyTotalRevenue} renderChart={renderTotalRevenueGrowth} height={240} responsive={true} ariaLabel="Total revenue growth" />
|
|
1213
|
+
</div>
|
|
1214
|
+
) : (
|
|
1215
|
+
<div className="h-[240px] flex items-center justify-center text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">Loading chart data...</div>
|
|
1216
|
+
)}
|
|
1217
|
+
</div>
|
|
1218
|
+
</div>
|
|
1219
|
+
</div>
|
|
1220
|
+
)}
|
|
1221
|
+
|
|
1222
|
+
{/* Invoices & Contract */}
|
|
1223
|
+
{isLoading ? (
|
|
1224
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
1225
|
+
<CardSkeleton lines={5} />
|
|
1226
|
+
<CardSkeleton lines={5} />
|
|
1227
|
+
</div>
|
|
1228
|
+
) : (
|
|
1229
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
1230
|
+
<ListCard
|
|
1231
|
+
title="Your invoices"
|
|
1232
|
+
subtitle="Recent statements"
|
|
1233
|
+
items={myInvoices.map((inv) => ({
|
|
1234
|
+
id: inv.id,
|
|
1235
|
+
title: inv.title,
|
|
1236
|
+
description: inv.description,
|
|
1237
|
+
status: inv.status,
|
|
1238
|
+
value: `$${inv.amount.toLocaleString()}`,
|
|
1239
|
+
timestamp: `Due ${inv.due}`,
|
|
1240
|
+
}))}
|
|
1241
|
+
maxBodyHeight={300}
|
|
1242
|
+
showStatus={true}
|
|
1243
|
+
showTimestamp={true}
|
|
1244
|
+
dense={false}
|
|
1245
|
+
divided={true}
|
|
1246
|
+
onItemClick={(item) => {
|
|
1247
|
+
toast.info(`Opening invoice ${item.title.split(' — ')[0]}`);
|
|
1248
|
+
}}
|
|
1249
|
+
emptyMessage="No invoices right now."
|
|
1250
|
+
loading={isLoading}
|
|
1251
|
+
/>
|
|
1252
|
+
|
|
1253
|
+
<div className="bg-white dark:bg-[var(--color-dash-text)] border border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30 rounded-xl shadow-sm hover:shadow-lg transition-shadow duration-300 overflow-hidden">
|
|
1254
|
+
<div className="p-6 border-b border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
|
|
1255
|
+
<h3 className="text-xl font-bold text-[var(--color-dash-text)] dark:text-white mb-1">
|
|
1256
|
+
Your Contract
|
|
1257
|
+
</h3>
|
|
1258
|
+
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1259
|
+
Partnership terms
|
|
1260
|
+
</p>
|
|
1261
|
+
</div>
|
|
1262
|
+
<div className="p-6 space-y-4">
|
|
1263
|
+
<div className="flex items-center justify-between pb-4 border-b border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
|
|
1264
|
+
<div>
|
|
1265
|
+
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Contract ID</p>
|
|
1266
|
+
<p className="text-lg font-bold text-[var(--color-dash-text)] dark:text-white">CNTR-00002</p>
|
|
1267
|
+
</div>
|
|
1268
|
+
<span className="inline-flex items-center rounded-full px-3 py-1 text-xs font-medium bg-[var(--color-dash-success)]/10 text-[var(--color-dash-success)] border border-[var(--color-dash-success)]/30">
|
|
1269
|
+
Active
|
|
1270
|
+
</span>
|
|
1271
|
+
</div>
|
|
1272
|
+
|
|
1273
|
+
<div className="grid grid-cols-2 gap-4">
|
|
1274
|
+
<div>
|
|
1275
|
+
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Commission Rate</p>
|
|
1276
|
+
<p className="text-2xl font-bold text-[var(--color-dash-success)]">17%</p>
|
|
1277
|
+
</div>
|
|
1278
|
+
<div>
|
|
1279
|
+
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Contract Term</p>
|
|
1280
|
+
<p className="text-sm font-semibold text-[var(--color-dash-text)] dark:text-white">Mar 2025 - Feb 2027</p>
|
|
1281
|
+
</div>
|
|
1282
|
+
</div>
|
|
1283
|
+
|
|
1284
|
+
<div className="bg-[var(--color-dash-surface)] dark:bg-[var(--color-dash-muted)]/10 rounded-lg p-4 space-y-3">
|
|
1285
|
+
<div>
|
|
1286
|
+
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Attrition Method</p>
|
|
1287
|
+
<p className="text-sm font-semibold text-[var(--color-dash-text)] dark:text-white">Per Night (80% threshold)</p>
|
|
1288
|
+
</div>
|
|
1289
|
+
<div>
|
|
1290
|
+
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Resale Credit Policy</p>
|
|
1291
|
+
<p className="text-sm font-semibold text-[var(--color-dash-text)] dark:text-white">Partial Credit (50%)</p>
|
|
1292
|
+
</div>
|
|
1293
|
+
</div>
|
|
1294
|
+
|
|
1295
|
+
<div className="pt-2">
|
|
1296
|
+
<button
|
|
1297
|
+
onClick={() => toast.info("Opening full contract PDF...")}
|
|
1298
|
+
className="w-full inline-flex items-center justify-center gap-2 px-4 py-3 bg-[var(--color-dash-surface)] dark:bg-[var(--color-dash-muted)]/20 hover:bg-[var(--color-dash-accent)]/10 dark:hover:bg-[var(--color-dash-accent)]/10 text-[var(--color-dash-text)] dark:text-white font-semibold rounded-lg border border-[var(--color-dash-label)]/30 dark:border-[var(--color-dash-muted)]/50 hover:border-[var(--color-dash-accent)] transition-colors text-sm"
|
|
1299
|
+
>
|
|
1300
|
+
<DocumentArrowDownIcon className="h-4 w-4" />
|
|
1301
|
+
Download Full Contract
|
|
1302
|
+
</button>
|
|
1303
|
+
</div>
|
|
1304
|
+
</div>
|
|
1305
|
+
</div>
|
|
1306
|
+
</div>
|
|
1307
|
+
)}
|
|
1308
|
+
|
|
1309
|
+
{/* Section — Recent Activity */}
|
|
1096
1310
|
<div className="pt-8 space-y-2">
|
|
1097
1311
|
<h2 className="text-3xl font-bold text-[var(--color-dash-text)] dark:text-white tracking-tight">
|
|
1098
1312
|
Recent activity
|
|
@@ -1102,8 +1316,6 @@ export default function PartnerHubDashboard() {
|
|
|
1102
1316
|
</p>
|
|
1103
1317
|
</div>
|
|
1104
1318
|
|
|
1105
|
-
{/* Hero penalty section removed - now at top of page */}
|
|
1106
|
-
|
|
1107
1319
|
{/* Action Items Grid */}
|
|
1108
1320
|
{isLoading ? (
|
|
1109
1321
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
|
@@ -1265,154 +1477,6 @@ export default function PartnerHubDashboard() {
|
|
|
1265
1477
|
</div>
|
|
1266
1478
|
)}
|
|
1267
1479
|
|
|
1268
|
-
{/* Section */}
|
|
1269
|
-
<div className="pt-8 space-y-2">
|
|
1270
|
-
<h2 className="text-3xl font-bold text-[var(--color-dash-text)] dark:text-white tracking-tight">
|
|
1271
|
-
Billing & contract details
|
|
1272
|
-
</h2>
|
|
1273
|
-
<p className="text-lg text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1274
|
-
Keep track of invoices and your partnership terms
|
|
1275
|
-
</p>
|
|
1276
|
-
</div>
|
|
1277
|
-
|
|
1278
|
-
{/* Revenue Trend by Property */}
|
|
1279
|
-
{isLoading ? (
|
|
1280
|
-
<CardSkeleton lines={6} />
|
|
1281
|
-
) : (
|
|
1282
|
-
<div className="bg-white dark:bg-[var(--color-dash-text)] border border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30 rounded-xl shadow-sm hover:shadow-lg transition-shadow duration-300 overflow-hidden">
|
|
1283
|
-
<div className="p-8 border-b border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
|
|
1284
|
-
<div className="flex items-start justify-between gap-4">
|
|
1285
|
-
<div>
|
|
1286
|
-
<h3 className="text-2xl font-bold text-[var(--color-dash-text)] dark:text-white mb-1">
|
|
1287
|
-
Revenue trend by property
|
|
1288
|
-
</h3>
|
|
1289
|
-
<p className="text-base text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1290
|
-
Monthly revenue earned through Engine across your {revenueTrendByProperty.properties?.length || 4} properties
|
|
1291
|
-
</p>
|
|
1292
|
-
</div>
|
|
1293
|
-
</div>
|
|
1294
|
-
{/* Legend */}
|
|
1295
|
-
<div className="flex flex-wrap gap-4 mt-5">
|
|
1296
|
-
{revenueTrendByProperty.properties.map((prop) => (
|
|
1297
|
-
<div key={prop.name} className="flex items-center gap-2">
|
|
1298
|
-
<span
|
|
1299
|
-
className="inline-block h-2.5 w-2.5 rounded-full flex-shrink-0"
|
|
1300
|
-
style={{ backgroundColor: prop.color }}
|
|
1301
|
-
/>
|
|
1302
|
-
<span className="text-xs font-medium text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1303
|
-
{prop.name}
|
|
1304
|
-
</span>
|
|
1305
|
-
</div>
|
|
1306
|
-
))}
|
|
1307
|
-
</div>
|
|
1308
|
-
</div>
|
|
1309
|
-
<div className="p-6 w-full">
|
|
1310
|
-
{revenueTrendByProperty && revenueTrendByProperty.months && revenueTrendByProperty.properties ? (
|
|
1311
|
-
<div className="w-full" style={{ minHeight: '260px' }}>
|
|
1312
|
-
<D3Chart
|
|
1313
|
-
data={revenueTrendByProperty}
|
|
1314
|
-
renderChart={renderRevenueTrendByProperty}
|
|
1315
|
-
height={260}
|
|
1316
|
-
responsive={true}
|
|
1317
|
-
ariaLabel="Revenue trend by property"
|
|
1318
|
-
/>
|
|
1319
|
-
</div>
|
|
1320
|
-
) : (
|
|
1321
|
-
<div className="h-[260px] flex items-center justify-center text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1322
|
-
Loading chart data...
|
|
1323
|
-
</div>
|
|
1324
|
-
)}
|
|
1325
|
-
</div>
|
|
1326
|
-
</div>
|
|
1327
|
-
)}
|
|
1328
|
-
|
|
1329
|
-
{/* Invoices & Contract */}
|
|
1330
|
-
{isLoading ? (
|
|
1331
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
1332
|
-
<CardSkeleton lines={5} />
|
|
1333
|
-
<CardSkeleton lines={5} />
|
|
1334
|
-
</div>
|
|
1335
|
-
) : (
|
|
1336
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
1337
|
-
<ListCard
|
|
1338
|
-
title="Your invoices"
|
|
1339
|
-
subtitle="Recent statements"
|
|
1340
|
-
items={myInvoices.map((inv) => ({
|
|
1341
|
-
id: inv.id,
|
|
1342
|
-
title: inv.title,
|
|
1343
|
-
description: inv.description,
|
|
1344
|
-
status: inv.status,
|
|
1345
|
-
value: `$${inv.amount.toLocaleString()}`,
|
|
1346
|
-
timestamp: `Due ${inv.due}`,
|
|
1347
|
-
}))}
|
|
1348
|
-
maxBodyHeight={300}
|
|
1349
|
-
showStatus={true}
|
|
1350
|
-
showTimestamp={true}
|
|
1351
|
-
dense={false}
|
|
1352
|
-
divided={true}
|
|
1353
|
-
onItemClick={(item) => {
|
|
1354
|
-
toast.info(`Opening invoice ${item.title.split(' — ')[0]}`);
|
|
1355
|
-
}}
|
|
1356
|
-
emptyMessage="No invoices right now."
|
|
1357
|
-
loading={isLoading}
|
|
1358
|
-
/>
|
|
1359
|
-
|
|
1360
|
-
<div className="bg-white dark:bg-[var(--color-dash-text)] border border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30 rounded-xl shadow-sm hover:shadow-lg transition-shadow duration-300 overflow-hidden">
|
|
1361
|
-
<div className="p-6 border-b border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
|
|
1362
|
-
<h3 className="text-xl font-bold text-[var(--color-dash-text)] dark:text-white mb-1">
|
|
1363
|
-
Your Contract
|
|
1364
|
-
</h3>
|
|
1365
|
-
<p className="text-sm text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)]">
|
|
1366
|
-
Partnership terms
|
|
1367
|
-
</p>
|
|
1368
|
-
</div>
|
|
1369
|
-
<div className="p-6 space-y-4">
|
|
1370
|
-
<div className="flex items-center justify-between pb-4 border-b border-[var(--color-dash-label)]/20 dark:border-[var(--color-dash-muted)]/30">
|
|
1371
|
-
<div>
|
|
1372
|
-
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Contract ID</p>
|
|
1373
|
-
<p className="text-lg font-bold text-[var(--color-dash-text)] dark:text-white">CNTR-00002</p>
|
|
1374
|
-
</div>
|
|
1375
|
-
<span className="inline-flex items-center rounded-full px-3 py-1 text-xs font-medium bg-[var(--color-dash-success)]/10 text-[var(--color-dash-success)] border border-[var(--color-dash-success)]/30">
|
|
1376
|
-
Active
|
|
1377
|
-
</span>
|
|
1378
|
-
</div>
|
|
1379
|
-
|
|
1380
|
-
<div className="grid grid-cols-2 gap-4">
|
|
1381
|
-
<div>
|
|
1382
|
-
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Commission Rate</p>
|
|
1383
|
-
<p className="text-2xl font-bold text-[var(--color-dash-success)]">17%</p>
|
|
1384
|
-
</div>
|
|
1385
|
-
<div>
|
|
1386
|
-
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Contract Term</p>
|
|
1387
|
-
<p className="text-sm font-semibold text-[var(--color-dash-text)] dark:text-white">Mar 2025 - Feb 2027</p>
|
|
1388
|
-
</div>
|
|
1389
|
-
</div>
|
|
1390
|
-
|
|
1391
|
-
<div className="bg-[var(--color-dash-surface)] dark:bg-[var(--color-dash-muted)]/10 rounded-lg p-4 space-y-3">
|
|
1392
|
-
<div>
|
|
1393
|
-
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Attrition Method</p>
|
|
1394
|
-
<p className="text-sm font-semibold text-[var(--color-dash-text)] dark:text-white">Per Night (80% threshold)</p>
|
|
1395
|
-
</div>
|
|
1396
|
-
<div>
|
|
1397
|
-
<p className="text-xs text-[var(--color-dash-muted)] dark:text-[var(--color-dash-label)] mb-1 uppercase tracking-wider">Resale Credit Policy</p>
|
|
1398
|
-
<p className="text-sm font-semibold text-[var(--color-dash-text)] dark:text-white">Partial Credit (50%)</p>
|
|
1399
|
-
</div>
|
|
1400
|
-
</div>
|
|
1401
|
-
|
|
1402
|
-
<div className="pt-2">
|
|
1403
|
-
<button
|
|
1404
|
-
onClick={() => toast.info("Opening full contract PDF...")}
|
|
1405
|
-
className="w-full inline-flex items-center justify-center gap-2 px-4 py-3 bg-[var(--color-dash-surface)] dark:bg-[var(--color-dash-muted)]/20 hover:bg-[var(--color-dash-accent)]/10 dark:hover:bg-[var(--color-dash-accent)]/10 text-[var(--color-dash-text)] dark:text-white font-semibold rounded-lg border border-[var(--color-dash-label)]/30 dark:border-[var(--color-dash-muted)]/50 hover:border-[var(--color-dash-accent)] transition-colors text-sm"
|
|
1406
|
-
>
|
|
1407
|
-
<DocumentArrowDownIcon className="h-4 w-4" />
|
|
1408
|
-
Download Full Contract
|
|
1409
|
-
</button>
|
|
1410
|
-
</div>
|
|
1411
|
-
</div>
|
|
1412
|
-
</div>
|
|
1413
|
-
</div>
|
|
1414
|
-
)}
|
|
1415
|
-
|
|
1416
1480
|
{/* Section */}
|
|
1417
1481
|
<div className="pt-8 space-y-2">
|
|
1418
1482
|
<h2 className="text-3xl font-bold text-[var(--color-dash-text)] dark:text-white tracking-tight">
|
package/brands/engine/global.css
CHANGED
|
@@ -98,8 +98,8 @@
|
|
|
98
98
|
--dash-surface: #fef9ef;
|
|
99
99
|
--dash-border: #e2c97a;
|
|
100
100
|
--dash-accent: #FFB200;
|
|
101
|
-
--dash-success: #
|
|
102
|
-
--dash-info: #
|
|
101
|
+
--dash-success: #34d399;
|
|
102
|
+
--dash-info: #67e8f9;
|
|
103
103
|
--dash-warning: #FD4B23;
|
|
104
104
|
--dash-danger: #dc2626;
|
|
105
105
|
--dash-dark: #0D1117;
|
|
@@ -110,9 +110,6 @@
|
|
|
110
110
|
--dash-chart-4: #FD4B23;
|
|
111
111
|
--dash-metric-size: 3.25rem;
|
|
112
112
|
--dash-metric-sub: 2.25rem;
|
|
113
|
-
--dash-pct-size: 0.875rem;
|
|
114
|
-
--dash-pct-px: 0.75rem;
|
|
115
|
-
--dash-pct-py: 0.25rem;
|
|
116
113
|
--color-dash-text: var(--dash-text);
|
|
117
114
|
--color-dash-muted: var(--dash-muted);
|
|
118
115
|
--color-dash-label: var(--dash-label);
|
package/dist/styles/global.css
CHANGED
|
@@ -95,11 +95,8 @@
|
|
|
95
95
|
--dash-chart-2: #16a34a;
|
|
96
96
|
--dash-chart-3: #e11d48;
|
|
97
97
|
--dash-chart-4: #7c3aed;
|
|
98
|
-
--dash-metric-size:
|
|
99
|
-
--dash-metric-sub:
|
|
100
|
-
--dash-pct-size: 0.75rem;
|
|
101
|
-
--dash-pct-px: 0.5rem;
|
|
102
|
-
--dash-pct-py: 0.125rem;
|
|
98
|
+
--dash-metric-size: 3.25rem;
|
|
99
|
+
--dash-metric-sub: 2.25rem;
|
|
103
100
|
--color-dash-text: var(--dash-text);
|
|
104
101
|
--color-dash-muted: var(--dash-muted);
|
|
105
102
|
--color-dash-label: var(--dash-label);
|
package/package.json
CHANGED
package/src/styles/global.css
CHANGED
|
@@ -95,11 +95,8 @@
|
|
|
95
95
|
--dash-chart-2: #16a34a;
|
|
96
96
|
--dash-chart-3: #e11d48;
|
|
97
97
|
--dash-chart-4: #7c3aed;
|
|
98
|
-
--dash-metric-size:
|
|
99
|
-
--dash-metric-sub:
|
|
100
|
-
--dash-pct-size: 0.75rem;
|
|
101
|
-
--dash-pct-px: 0.5rem;
|
|
102
|
-
--dash-pct-py: 0.125rem;
|
|
98
|
+
--dash-metric-size: 3.25rem;
|
|
99
|
+
--dash-metric-sub: 2.25rem;
|
|
103
100
|
--color-dash-text: var(--dash-text);
|
|
104
101
|
--color-dash-muted: var(--dash-muted);
|
|
105
102
|
--color-dash-label: var(--dash-label);
|