File size: 15,033 Bytes
7dff677
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778ab74
7dff677
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aa3c3cf
 
 
 
7dff677
 
 
 
 
 
 
aa3c3cf
 
 
 
 
 
7dff677
aa3c3cf
 
7dff677
 
 
 
 
 
 
 
 
 
 
 
 
aa3c3cf
7dff677
 
 
 
aa3c3cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7dff677
 
 
 
 
 
 
 
 
 
 
 
aa3c3cf
778ab74
 
7dff677
 
 
 
778ab74
 
7dff677
 
 
 
778ab74
 
7dff677
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aa3c3cf
 
 
7dff677
aa3c3cf
 
 
 
 
 
7dff677
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
import React, { forwardRef } from 'react'

export interface ReportProps {
  form: {
    selected_name: string
    current_club: string
    interested_club: string
    contract_years: number
    age: number
    injuries_24m: number
    asking_price: number
    market_value_estimation: number
  }
  result: {
    ledger: {
      intrinsic_performance_value: number
      category: string
      depreciation: number
      baseline_value: number
      external_multiplier: number
      hard_cap: number
    }
    nlp_results?: {
      durability: number
      recency: number
      agent: number
    }
    nlp_found?: boolean
  }
}

export const ReportTemplate = forwardRef<HTMLDivElement, ReportProps>(({ form, result }, ref) => {
  const L = result.ledger
  const isOverpay = form.asking_price > L.hard_cap
  const dateStr = new Date().toLocaleString('en-US', { dateStyle: 'long', timeStyle: 'short' })

  return (
    <div
      ref={ref}
      className="printable-report"
      style={{
        backgroundColor: '#ffffff',
        color: '#0f172a',
        fontFamily: "'Inter', sans-serif",
        boxSizing: 'border-box',
        display: 'none', // Hidden on screen, shown in print via CSS
      }}
    >
      {/* HEADER */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', borderBottom: '2px solid #e2e8f0', paddingBottom: '24px', marginBottom: '32px' }}>
        <div>
          <h1 style={{ fontSize: '32px', fontWeight: 800, margin: 0, color: '#020617', letterSpacing: '-0.03em' }}>
            FairValue Strategic Report
          </h1>
          <p style={{ fontSize: '14px', color: '#64748b', marginTop: '4px' }}>
            AI-Driven Transfer Valuation Intelligence
          </p>
        </div>
        <div style={{ textAlign: 'right', fontSize: '12px', color: '#475569', lineHeight: 1.6 }}>
          <div style={{ fontWeight: 600, color: '#0f172a' }}>Lawrence Oladeji</div>
          <div>oladeji.lawrence@gmail.com</div>
          <div><a href="https://wa.me/2349038819790" style={{ color: '#0f172a', textDecoration: 'none' }}>WhatsApp</a></div>
          <div><a href="https://premiership-player-fair-value.vercel.app/" style={{ color: '#2563eb', textDecoration: 'none' }}>Website</a></div>
          <div style={{ marginTop: '8px', color: '#94a3b8' }}>Generated: {dateStr}</div>
        </div>
      </div>

      {/* PLAYER PROFILE */}
      <div style={{ marginBottom: '32px', pageBreakInside: 'avoid', breakInside: 'avoid' }}>
        <h2 style={{ fontSize: '18px', fontWeight: 700, color: '#334155', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '16px' }}>
          Player Profile & Parameters
        </h2>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', background: '#f8fafc', padding: '24px', borderRadius: '12px', border: '1px solid #e2e8f0' }}>
          <div>
            <div style={{ fontSize: '11px', color: '#64748b', textTransform: 'uppercase' }}>Target Player</div>
            <div style={{ fontSize: '20px', fontWeight: 700, color: '#0f172a' }}>{form.selected_name || 'N/A'}</div>
          </div>
          <div>
            <div style={{ fontSize: '11px', color: '#64748b', textTransform: 'uppercase' }}>Transfer Direction</div>
            <div style={{ fontSize: '16px', fontWeight: 600, color: '#0f172a' }}>
              {form.current_club || 'Unknown'} → {form.interested_club || 'Unknown'}
            </div>
          </div>
          <div>
            <div style={{ fontSize: '11px', color: '#64748b', textTransform: 'uppercase' }}>Age</div>
            <div style={{ fontSize: '16px', fontWeight: 600, color: '#0f172a' }}>{form.age} years</div>
          </div>
          <div>
            <div style={{ fontSize: '11px', color: '#64748b', textTransform: 'uppercase' }}>Contract Remaining</div>
            <div style={{ fontSize: '16px', fontWeight: 600, color: '#0f172a' }}>{form.contract_years} years</div>
          </div>
        </div>
      </div>

      {/* FINANCIAL VALUATION LEDGER */}
      <div style={{ marginBottom: '32px', pageBreakInside: 'avoid', breakInside: 'avoid' }}>
        <h2 style={{ fontSize: '18px', fontWeight: 700, color: '#334155', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '16px' }}>
          AI Valuation Ledger
        </h2>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '14px' }}>
          <colgroup>
            <col style={{ width: '70%' }} />
            <col style={{ width: '30%' }} />
          </colgroup>
          <tbody>
            <tr style={{ borderBottom: '1px solid #e2e8f0' }}>
              <td style={{ padding: '12px 0', color: '#475569', fontWeight: 500 }}>Intrinsic Performance Value</td>
              <td style={{ padding: '12px 0', textAlign: 'right', fontWeight: 700, color: '#0f172a' }}>£{L.intrinsic_performance_value.toFixed(1)}m</td>
            </tr>
            <tr style={{ borderBottom: '1px solid #e2e8f0' }}>
              <td style={{ padding: '12px 0', color: '#475569', fontWeight: 500 }}>
                Age &amp; Contract Impact (SHAP) — {L.depreciation > 0 ? '📉 Depreciation' : '📈 Appreciation'}
                {L.depreciation > 0 && form.age <= 23 && (
                  <div style={{ fontSize: '11px', color: '#94a3b8', marginTop: '2px' }}>
                    * Model reflects current output, not future potential
                  </div>
                )}
              </td>
              <td style={{ padding: '12px 0', textAlign: 'right', fontWeight: 700, color: L.depreciation > 0 ? '#ef4444' : '#22c55e' }}>
                {L.depreciation > 0 ? '-' : '+'}£{Math.abs(L.depreciation).toFixed(1)}m
              </td>
            </tr>
            <tr style={{ borderBottom: '1px solid #e2e8f0' }}>
              <td style={{ padding: '12px 0', color: '#475569', fontWeight: 500 }}>ML Baseline Value</td>
              <td style={{ padding: '12px 0', textAlign: 'right', fontWeight: 700, color: '#0f172a' }}>£{L.baseline_value.toFixed(1)}m</td>
            </tr>
            <tr style={{ borderBottom: '1px solid #e2e8f0' }}>
              <td style={{ padding: '12px 0', color: '#475569', fontWeight: 500 }}>Live NLP Market Multiplier</td>
              <td style={{ padding: '12px 0', textAlign: 'right', fontWeight: 700, color: L.external_multiplier > 1 ? '#22c55e' : '#ef4444' }}>
                ×{L.external_multiplier.toFixed(3)}
              </td>
            </tr>
            <tr style={{ backgroundColor: '#f0fdf4', border: '1px solid #bbf7d0' }}>
              <td style={{ padding: '16px 12px', color: '#166534', fontWeight: 700, fontSize: '16px' }}>Calculated Fair Value (Ceiling)</td>
              <td style={{ padding: '16px 12px', textAlign: 'right', fontWeight: 800, fontSize: '20px', color: '#16a34a' }}>
                £{L.hard_cap.toFixed(1)}m
              </td>
            </tr>
            <tr style={{ backgroundColor: '#fefce8', border: '1px solid #fde68a' }}>
              <td style={{ padding: '12px 12px', color: '#92400e', fontWeight: 600, fontSize: '13px' }}>
                🎯 Recommended Opening Bid
              </td>
              <td style={{ padding: '12px 12px', textAlign: 'right', fontWeight: 700, fontSize: '15px', color: '#b45309' }}>
                £{(L.hard_cap * 0.85).toFixed(1)}m
              </td>
            </tr>
            <tr style={{ backgroundColor: '#fff7ed', border: '1px solid #fed7aa' }}>
              <td style={{ padding: '12px 12px', color: '#7c2d12', fontWeight: 600, fontSize: '13px' }}>
                ⚠️ Walk-Away Ceiling
              </td>
              <td style={{ padding: '12px 12px', textAlign: 'right', fontWeight: 700, fontSize: '15px', color: '#dc2626' }}>
                £{L.hard_cap.toFixed(1)}m
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      {/* NLP INTELLIGENCE BREAKDOWN */}
      {result.nlp_results && (
        <div style={{ marginBottom: '32px', pageBreakInside: 'avoid', breakInside: 'avoid' }}>
          <h2 style={{ fontSize: '18px', fontWeight: 700, color: '#334155', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '16px' }}>
            Live Market Intelligence (NLP Breakdown)
          </h2>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '16px', background: '#f8fafc', padding: '24px', borderRadius: '12px', border: '1px solid #e2e8f0' }}>
            <div>
              <div style={{ fontSize: '11px', color: '#64748b', textTransform: 'uppercase' }}>Recent Form &amp; Impact</div>
              <div style={{ fontSize: '18px', fontWeight: 700, color: (result.nlp_results?.recency ?? 0) === 0 ? (result.nlp_found ? '#475569' : '#94a3b8') : (result.nlp_results?.recency ?? 0) < 0 ? '#ef4444' : '#22c55e' }}>
                {(result.nlp_results?.recency ?? 0) === 0 ? (result.nlp_found ? 'Neutral / Factual' : 'No signals detected') : `${(result.nlp_results?.recency ?? 0) > 0 ? '+' : ''}${(result.nlp_results?.recency ?? 0).toFixed(2)}`}
              </div>
            </div>
            <div>
              <div style={{ fontSize: '11px', color: '#64748b', textTransform: 'uppercase' }}>Injury / Availability</div>
              <div style={{ fontSize: '18px', fontWeight: 700, color: (result.nlp_results?.durability ?? 0) === 0 ? (result.nlp_found ? '#475569' : '#94a3b8') : (result.nlp_results?.durability ?? 0) < 0 ? '#ef4444' : '#0f172a' }}>
                {(result.nlp_results?.durability ?? 0) === 0 ? (result.nlp_found ? 'Neutral / Factual' : 'No signals detected') : `${(result.nlp_results?.durability ?? 0) > 0 ? '+' : ''}${(result.nlp_results?.durability ?? 0).toFixed(2)}`}
              </div>
            </div>
            <div>
              <div style={{ fontSize: '11px', color: '#64748b', textTransform: 'uppercase' }}>Transfer Speculation</div>
              <div style={{ fontSize: '18px', fontWeight: 700, color: (result.nlp_results?.agent ?? 0) === 0 ? (result.nlp_found ? '#475569' : '#94a3b8') : (result.nlp_results?.agent ?? 0) < 0 ? '#ef4444' : '#22c55e' }}>
                {(result.nlp_results?.agent ?? 0) === 0 ? (result.nlp_found ? 'Neutral / Factual' : 'No signals detected') : `${(result.nlp_results?.agent ?? 0) > 0 ? '+' : ''}${(result.nlp_results?.agent ?? 0).toFixed(2)}`}
              </div>
            </div>
          </div>
          <div style={{ fontSize: '13px', color: '#64748b', marginTop: '12px', lineHeight: 1.5 }}>
            <strong>How this works:</strong> The Live NLP Market Multiplier (currently <strong>×{L.external_multiplier.toFixed(3)}</strong>) is calculated from the sentiment scores above. A multiplier of exactly 1.000 means perfectly neutral market hype. A score above 1.0 indicates high demand and positive news, allowing the selling club to charge a premium. A score below 1.0 indicates negative press (e.g. poor form or injury history), creating leverage to negotiate a discount.
          </div>
        </div>
      )}

      {/* VERDICT & SUMMARY */}
      <div style={{ marginBottom: '40px', pageBreakBefore: 'always', breakBefore: 'page' }}>
        <h2 style={{ fontSize: '18px', fontWeight: 700, color: '#334155', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '16px' }}>
          Executive Summary & Verdict
        </h2>
        <div style={{ padding: '24px', background: isOverpay ? '#fef2f2' : '#f0fdf4', border: `1px solid ${isOverpay ? '#fecaca' : '#bbf7d0'}`, borderRadius: '12px' }}>
          <p style={{ fontSize: '15px', color: isOverpay ? '#991b1b' : '#166534', lineHeight: 1.6, marginBottom: '16px' }}>
            <strong>Negotiation Intel:</strong> Based on the real-time evaluation engine, {form.selected_name}'s intrinsic value sits at £{L.intrinsic_performance_value.toFixed(1)}m.
            Age &amp; contract dynamics apply a {L.depreciation > 0 ? `depreciation of -£${Math.abs(L.depreciation).toFixed(1)}m` : `appreciation of +£${Math.abs(L.depreciation).toFixed(1)}m`},
            with live NLP market sentiment at ×{L.external_multiplier.toFixed(3)}. The absolute financial ceiling (Fair Value) is <strong>£{L.hard_cap.toFixed(1)}m</strong>.
            <br/><br/>
            <strong>Validation:</strong> {(result.nlp_results?.recency ?? 0) > 0 ? "Player's recent form commands a market premium." : "Recent form is suboptimal — leverage this to negotiate a lower fee."} {L.depreciation > 0 ? `Age & contract profile adds £${Math.abs(L.depreciation).toFixed(1)}m in depreciation risk — use this as a negotiation lever.` : `Young age and contract security add £${Math.abs(L.depreciation).toFixed(1)}m in appreciation value, justifying a strong offer.`}
            {L.depreciation > 0 && form.age <= 23 && (
              <span style={{ display: 'block', marginTop: '8px', fontSize: '12px', color: '#64748b' }}>
                ℹ️ Note: Depreciation reflects the player's current statistical output stage vs. their peak. Young players may command a future-value premium not captured in this model.
              </span>
            )}
          </p>
          <div style={{ fontSize: '18px', fontWeight: 800, color: isOverpay ? '#dc2626' : '#16a34a', borderTop: `1px solid ${isOverpay ? '#fca5a5' : '#86efac'}`, paddingTop: '16px' }}>
            VERDICT: {isOverpay ? 'OVERPAY RISK' : 'FAIR DEAL - PROCEED WITH CONFIDENCE'}
          </div>
          <div style={{ fontSize: '14px', color: isOverpay ? '#b91c1c' : '#15803d', marginTop: '6px' }}>
            The selling club's asking price of £{form.asking_price}m {isOverpay ? 'exceeds' : 'is safely within'} our calculated Fair Value.
          </div>
        </div>
      </div>

      {/* DEFINITION OF TERMS */}
      <div style={{ borderTop: '2px solid #e2e8f0', paddingTop: '24px', pageBreakInside: 'avoid', breakInside: 'avoid' }}>
        <h2 style={{ fontSize: '14px', fontWeight: 700, color: '#64748b', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '12px' }}>
          Definition of Terms
        </h2>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', fontSize: '12px', color: '#475569', lineHeight: 1.5 }}>
          <div>
            <strong style={{ color: '#0f172a' }}>Intrinsic Performance Value:</strong> Player's raw talent value derived purely from on-pitch statistics.
          </div>
          <div>
            <strong style={{ color: '#0f172a' }}>Age & Contract Impact:</strong> Financial adjustment based on age and remaining contract years.
          </div>
          <div>
            <strong style={{ color: '#0f172a' }}>NLP Multiplier:</strong> Live web-scraping adjustment factor. Values {'>'} 1.0 indicate positive hype (premium), while values {'<'} 1.0 indicate negative press (discount).
          </div>
          <div>
            <strong style={{ color: '#0f172a' }}>Fair Value:</strong> The absolute maximum recommended price (financial ceiling).
          </div>
        </div>
      </div>

    </div>
  )
})