Commit Β·
f85665c
1
Parent(s): 466c638
feat: HowItWorks - real curl examples with copy button + actual API endpoints (#26)
Browse files- feat: HowItWorks - real curl examples with copy button + actual API endpoints (a6501a5533595c0362defe51422e404839ce5ad3)
landing/src/components/HowItWorks.tsx
CHANGED
|
@@ -1,53 +1,128 @@
|
|
|
|
|
| 1 |
import './HowItWorks.css'
|
| 2 |
|
|
|
|
|
|
|
| 3 |
const steps = [
|
| 4 |
{
|
| 5 |
step: '01',
|
| 6 |
title: 'Geographic Clustering Agent',
|
| 7 |
desc: 'scikit-learn KMeans clusters shipments by pickup/drop proximity (4D feature vectors). Silhouette-score selects optimal K. Groups nearby shipments heading the same direction.',
|
| 8 |
-
code:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
color: '#f97316',
|
|
|
|
| 10 |
},
|
| 11 |
{
|
| 12 |
step: '02',
|
| 13 |
title: 'Time Window Compatibility Agent',
|
| 14 |
desc: 'Filters clusters by delivery time window overlap. Splits groups where shipments have incompatible schedules. Configurable tolerance (default: 120 min).',
|
| 15 |
-
code:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
color: '#3b82f6',
|
|
|
|
| 17 |
},
|
| 18 |
{
|
| 19 |
step: '03',
|
| 20 |
title: 'Capacity Optimization Agent',
|
| 21 |
desc: 'OR-Tools CP-SAT integer programming solver assigns shipments to trucks. Minimizes vehicles used while respecting weight + volume constraints. FFD heuristic fallback.',
|
| 22 |
-
code:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
color: '#10b981',
|
|
|
|
| 24 |
},
|
| 25 |
{
|
| 26 |
step: '04',
|
| 27 |
-
title: '
|
| 28 |
-
desc: '
|
| 29 |
-
code:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
color: '#f59e0b',
|
|
|
|
| 31 |
},
|
| 32 |
{
|
| 33 |
step: '05',
|
| 34 |
title: 'Continuous Learning Agent',
|
| 35 |
-
desc: 'Q-learning RL agent records (state, action, reward) per run. Builds Q-table over time to recommend optimal
|
| 36 |
-
code:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
color: '#ec4899',
|
|
|
|
| 38 |
},
|
| 39 |
]
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
export default function HowItWorks() {
|
| 42 |
return (
|
| 43 |
<section className="hiw" id="how-it-works">
|
| 44 |
<div className="container">
|
| 45 |
<div className="section-header">
|
| 46 |
-
<div className="tag">
|
| 47 |
-
<h2 className="section-title">How
|
| 48 |
<p className="section-sub">
|
| 49 |
-
|
| 50 |
-
|
| 51 |
</p>
|
| 52 |
</div>
|
| 53 |
|
|
@@ -67,7 +142,11 @@ export default function HowItWorks() {
|
|
| 67 |
<div className="hiw__step-content">
|
| 68 |
<h3 className="hiw__step-title">{s.title}</h3>
|
| 69 |
<p className="hiw__step-desc">{s.desc}</p>
|
|
|
|
|
|
|
|
|
|
| 70 |
<div className="hiw__step-code">
|
|
|
|
| 71 |
<pre><code>{s.code}</code></pre>
|
| 72 |
</div>
|
| 73 |
</div>
|
|
@@ -75,6 +154,14 @@ export default function HowItWorks() {
|
|
| 75 |
))}
|
| 76 |
</div>
|
| 77 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
</section>
|
| 79 |
)
|
| 80 |
}
|
|
|
|
| 1 |
+
import { useState } from 'react'
|
| 2 |
import './HowItWorks.css'
|
| 3 |
|
| 4 |
+
const API_URL = import.meta.env.VITE_API_URL || 'https://fairrelay-backend.onrender.com'
|
| 5 |
+
|
| 6 |
const steps = [
|
| 7 |
{
|
| 8 |
step: '01',
|
| 9 |
title: 'Geographic Clustering Agent',
|
| 10 |
desc: 'scikit-learn KMeans clusters shipments by pickup/drop proximity (4D feature vectors). Silhouette-score selects optimal K. Groups nearby shipments heading the same direction.',
|
| 11 |
+
code: `curl -X POST ${API_URL}/api/v1/consolidate/optimize \\
|
| 12 |
+
-H "Content-Type: application/json" \\
|
| 13 |
+
-d '{
|
| 14 |
+
"shipments": [
|
| 15 |
+
{"id": "SH-1", "pickupLat": 19.076, "pickupLng": 72.877,
|
| 16 |
+
"dropLat": 18.520, "dropLng": 73.856, "weight": 800}
|
| 17 |
+
],
|
| 18 |
+
"trucks": [{"id": "T-1", "maxWeight": 2000, "maxVolume": 8}]
|
| 19 |
+
}'`,
|
| 20 |
color: '#f97316',
|
| 21 |
+
endpoint: 'POST /api/v1/consolidate/optimize',
|
| 22 |
},
|
| 23 |
{
|
| 24 |
step: '02',
|
| 25 |
title: 'Time Window Compatibility Agent',
|
| 26 |
desc: 'Filters clusters by delivery time window overlap. Splits groups where shipments have incompatible schedules. Configurable tolerance (default: 120 min).',
|
| 27 |
+
code: `# Time windows are part of the shipment payload:
|
| 28 |
+
{
|
| 29 |
+
"shipments": [{
|
| 30 |
+
"id": "SH-1",
|
| 31 |
+
"timeWindowStart": "2026-02-20T06:00:00Z",
|
| 32 |
+
"timeWindowEnd": "2026-02-20T12:00:00Z",
|
| 33 |
+
...
|
| 34 |
+
}]
|
| 35 |
+
}
|
| 36 |
+
# Agent auto-splits groups with >120min gap`,
|
| 37 |
color: '#3b82f6',
|
| 38 |
+
endpoint: 'Integrated in consolidate pipeline',
|
| 39 |
},
|
| 40 |
{
|
| 41 |
step: '03',
|
| 42 |
title: 'Capacity Optimization Agent',
|
| 43 |
desc: 'OR-Tools CP-SAT integer programming solver assigns shipments to trucks. Minimizes vehicles used while respecting weight + volume constraints. FFD heuristic fallback.',
|
| 44 |
+
code: `# Response includes packed truck assignments:
|
| 45 |
+
{
|
| 46 |
+
"groups": [{
|
| 47 |
+
"groupId": 1,
|
| 48 |
+
"truckId": "T-1",
|
| 49 |
+
"shipmentCount": 3,
|
| 50 |
+
"totalWeight": 1850,
|
| 51 |
+
"utilizationWeight": 92.5
|
| 52 |
+
}],
|
| 53 |
+
"metrics": {
|
| 54 |
+
"utilizationBefore": 27.3,
|
| 55 |
+
"utilizationAfter": 82.1,
|
| 56 |
+
"tripsReduced": 4
|
| 57 |
+
}
|
| 58 |
+
}`,
|
| 59 |
color: '#10b981',
|
| 60 |
+
endpoint: 'Response from /consolidate/optimize',
|
| 61 |
},
|
| 62 |
{
|
| 63 |
step: '04',
|
| 64 |
+
title: 'Fair Dispatch Engine (8 Agents)',
|
| 65 |
+
desc: 'LangGraph multi-agent workflow: ML Effort β Route Planner (OR-Tools) β Fairness Manager (Gini β€ 0.33) β Driver Liaison β Final Resolution β Explainability.',
|
| 66 |
+
code: `curl -X POST ${API_URL}/api/dispatch/allocate \\
|
| 67 |
+
-H "Content-Type: application/json" \\
|
| 68 |
+
-d '{
|
| 69 |
+
"drivers": [
|
| 70 |
+
{"id": "D-1", "name": "Rajesh", "vehicle_capacity_kg": 500}
|
| 71 |
+
],
|
| 72 |
+
"packages": [
|
| 73 |
+
{"id": "P-1", "weight_kg": 12, "latitude": 19.13,
|
| 74 |
+
"longitude": 72.82, "priority": "HIGH"}
|
| 75 |
+
],
|
| 76 |
+
"warehouse": {"lat": 19.076, "lng": 72.877}
|
| 77 |
+
}'`,
|
| 78 |
color: '#f59e0b',
|
| 79 |
+
endpoint: 'POST /api/dispatch/allocate',
|
| 80 |
},
|
| 81 |
{
|
| 82 |
step: '05',
|
| 83 |
title: 'Continuous Learning Agent',
|
| 84 |
+
desc: 'Q-learning RL agent records (state, action, reward) per run. Builds Q-table over time to recommend optimal parameters. Self-improves with every execution.',
|
| 85 |
+
code: `# Health check β verify all agents are active:
|
| 86 |
+
curl ${API_URL}/api/dispatch/health
|
| 87 |
+
|
| 88 |
+
# Response:
|
| 89 |
+
{
|
| 90 |
+
"brain_status": "connected",
|
| 91 |
+
"brain_health": {"status": "healthy", "database": "connected"},
|
| 92 |
+
"gateway": "operational"
|
| 93 |
+
}`,
|
| 94 |
color: '#ec4899',
|
| 95 |
+
endpoint: 'GET /api/dispatch/health',
|
| 96 |
},
|
| 97 |
]
|
| 98 |
|
| 99 |
+
function CopyButton({ text }: { text: string }) {
|
| 100 |
+
const [copied, setCopied] = useState(false)
|
| 101 |
+
|
| 102 |
+
const handleCopy = () => {
|
| 103 |
+
navigator.clipboard.writeText(text).then(() => {
|
| 104 |
+
setCopied(true)
|
| 105 |
+
setTimeout(() => setCopied(false), 2000)
|
| 106 |
+
})
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
return (
|
| 110 |
+
<button onClick={handleCopy} className="hiw__copy-btn" title="Copy to clipboard">
|
| 111 |
+
{copied ? 'β Copied' : 'π Copy'}
|
| 112 |
+
</button>
|
| 113 |
+
)
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
export default function HowItWorks() {
|
| 117 |
return (
|
| 118 |
<section className="hiw" id="how-it-works">
|
| 119 |
<div className="container">
|
| 120 |
<div className="section-header">
|
| 121 |
+
<div className="tag">Multi-Agent Pipeline</div>
|
| 122 |
+
<h2 className="section-title">How FairRelay's AI Engine works</h2>
|
| 123 |
<p className="section-sub">
|
| 124 |
+
13 specialized AI agents orchestrated by LangGraph β 8 for fair dispatch + 5 for load consolidation.
|
| 125 |
+
Every endpoint is live. Try the curl commands below.
|
| 126 |
</p>
|
| 127 |
</div>
|
| 128 |
|
|
|
|
| 142 |
<div className="hiw__step-content">
|
| 143 |
<h3 className="hiw__step-title">{s.title}</h3>
|
| 144 |
<p className="hiw__step-desc">{s.desc}</p>
|
| 145 |
+
<div className="hiw__step-endpoint" style={{ color: s.color }}>
|
| 146 |
+
<code>{s.endpoint}</code>
|
| 147 |
+
</div>
|
| 148 |
<div className="hiw__step-code">
|
| 149 |
+
<CopyButton text={s.code} />
|
| 150 |
<pre><code>{s.code}</code></pre>
|
| 151 |
</div>
|
| 152 |
</div>
|
|
|
|
| 154 |
))}
|
| 155 |
</div>
|
| 156 |
</div>
|
| 157 |
+
|
| 158 |
+
<style>{`
|
| 159 |
+
.hiw__copy-btn { position: absolute; top: 8px; right: 8px; background: rgba(249,115,22,0.15); border: 1px solid rgba(249,115,22,0.3); color: #f97316; font-size: 0.7rem; padding: 4px 10px; border-radius: 6px; cursor: pointer; font-weight: 600; z-index: 2; transition: all 0.2s; }
|
| 160 |
+
.hiw__copy-btn:hover { background: rgba(249,115,22,0.25); }
|
| 161 |
+
.hiw__step-code { position: relative; }
|
| 162 |
+
.hiw__step-endpoint { font-size: 0.7rem; font-family: 'JetBrains Mono', monospace; margin-bottom: 0.5rem; opacity: 0.8; }
|
| 163 |
+
.hiw__step-endpoint code { background: rgba(255,255,255,0.03); padding: 2px 8px; border-radius: 4px; border: 1px solid rgba(255,255,255,0.06); }
|
| 164 |
+
`}</style>
|
| 165 |
</section>
|
| 166 |
)
|
| 167 |
}
|