Files
tink-demo/src/templates/step.html

243 lines
13 KiB
HTML
Raw Normal View History

2026-05-22 18:30:59 +02:00
{% extends "base.html" %}
{% block title %} — Step {{ step }}{% endblock %}
{% block stepper %}
<div class="bg-slate-900/60 border-b border-slate-800">
<div class="max-w-6xl mx-auto px-4 py-3">
<div class="flex items-center gap-1 overflow-x-auto">
{% set step_names = ["Auth", "Opret Bruger", "Tilslut Bank", "Konti", "Transaktioner", "Events"] %}
{% for i in range(1, 7) %}
<a href="/demo/step/{{ i }}"
class="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm whitespace-nowrap transition
{% if i == step %}bg-violet-600 text-white font-semibold
{% elif i < step %}text-slate-300 hover:text-white
{% else %}text-slate-600 hover:text-slate-400{% endif %}">
<span class="w-5 h-5 rounded-full text-xs font-bold flex items-center justify-center
{% if i < step %}bg-slate-700 text-slate-300
{% elif i == step %}bg-violet-500 text-white
{% else %}bg-slate-800 text-slate-600{% endif %}">{{ i }}</span>
{{ step_names[i-1] }}
</a>
{% if i < 6 %}
<span class="text-slate-700"></span>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="grid grid-cols-1 lg:grid-cols-5 gap-6">
<!-- Left: info panel -->
<div class="lg:col-span-2 space-y-4">
<!-- Step header -->
<div>
<div class="flex items-center gap-2 mb-2">
<span class="w-8 h-8 rounded-full bg-violet-600 text-white text-sm font-bold flex items-center justify-center">{{ step }}</span>
<div>
<h2 class="text-xl font-bold text-white">{{ title }}</h2>
<p class="text-slate-400 text-sm">{{ subtitle }}</p>
</div>
</div>
</div>
<!-- Endpoint badge -->
<div class="bg-slate-900 border border-slate-800 rounded-xl p-4">
<div class="flex items-center justify-between mb-2">
<span class="text-xs text-slate-500 uppercase tracking-wider">Endpoint</span>
<span class="text-xs px-2 py-0.5 rounded-full font-mono font-semibold
{% if 'v2' in api_version %}bg-violet-900/50 text-violet-300 border border-violet-700/40
{% else %}bg-slate-800 text-slate-400{% endif %}">
{{ api_version }}
</span>
</div>
<code class="text-sm text-emerald-400 font-mono break-all">{{ endpoint }}</code>
</div>
<!-- Description -->
<div class="bg-slate-900 border border-slate-800 rounded-xl p-4">
<p class="text-slate-300 text-sm leading-relaxed">{{ description }}</p>
</div>
<!-- curl example -->
<div class="bg-slate-900 border border-slate-800 rounded-xl p-4">
<div class="flex items-center justify-between mb-3">
<span class="text-xs text-slate-500 uppercase tracking-wider">cURL eksempel</span>
<button onclick="copyToClipboard('curl-{{ step }}')"
class="text-xs text-slate-400 hover:text-white transition px-2 py-1 rounded bg-slate-800 hover:bg-slate-700">
Kopier
</button>
</div>
<pre id="curl-{{ step }}" class="text-xs text-amber-300 font-mono whitespace-pre-wrap leading-relaxed">{{ curl_example }}</pre>
</div>
<!-- Navigation -->
<div class="flex gap-3">
{% if prev_step %}
<a href="/demo/step/{{ prev_step }}"
class="flex-1 text-center px-4 py-2.5 border border-slate-700 text-slate-300 hover:text-white hover:border-slate-500 rounded-xl text-sm transition">
← Step {{ prev_step }}
</a>
{% endif %}
{% if next_step %}
<a href="/demo/step/{{ next_step }}"
class="flex-1 text-center px-4 py-2.5 bg-violet-600 hover:bg-violet-500 text-white rounded-xl text-sm font-semibold transition">
Step {{ next_step }} →
</a>
{% endif %}
</div>
</div>
<!-- Right: response panel -->
<div class="lg:col-span-3 space-y-4">
<!-- Tink Link special button (step 3) -->
{% if tink_link_url %}
{% if cb_success %}
<!-- Already connected — show success, hide connection UI -->
<div class="bg-emerald-950/60 border border-emerald-700/50 rounded-xl p-5 flex items-start gap-4">
<div class="w-10 h-10 rounded-full bg-emerald-900/60 flex items-center justify-center flex-shrink-0">
<svg class="w-5 h-5 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
</div>
<div class="flex-1">
<p class="text-emerald-300 font-semibold text-base">Bank forbundet!</p>
<p class="text-emerald-400/70 text-sm mt-0.5">User token gemt i session. Trin 46 er klar.</p>
<a href="/demo/reset"
class="inline-flex items-center gap-1.5 mt-3 text-xs text-slate-500 hover:text-slate-300 transition">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
Start forfra
</a>
</div>
</div>
{% else %}
<!-- Not yet connected — show connection UI -->
<!-- PRIMARY: console.tink.com/callback (always works, no redirect URI registration needed) -->
<div class="bg-slate-900 border border-emerald-700/40 rounded-xl p-5 space-y-4">
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded-full bg-emerald-900/50 flex items-center justify-center flex-shrink-0">
<svg class="w-4 h-4 text-emerald-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>
</div>
<div>
<h3 class="text-white font-semibold mb-1">Tilslut testbank</h3>
<p class="text-slate-400 text-sm">Åbn Tink Link, forbind Demo Bank, kopier koden og indsæt herunder.</p>
</div>
</div>
<!-- Instructions -->
<div class="bg-slate-800/60 border border-slate-700/50 rounded-lg p-4 text-sm space-y-2">
<p class="text-slate-300 font-semibold flex items-center gap-1.5">
<svg class="w-4 h-4 text-amber-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
Sådan forbinder du Demo Bank
</p>
<ol class="text-slate-400 space-y-1.5 list-decimal list-inside leading-relaxed">
<li>Hent credentials fra <span class="font-mono text-amber-300 text-xs bg-slate-900 px-1.5 py-0.5 rounded">Console → Demo Bank → Transactions → DK</span></li>
<li>Klik <strong class="text-white">"Åbn Tink Link"</strong> nedenfor (åbner i ny fane)</li>
<li>Vælg <span class="text-slate-300">Tink Demo Bank</span><span class="text-slate-300">Open Banking</span><span class="text-slate-300">Password And OTP</span></li>
<li>Indtast username + password → OTP-koden vises på siden</li>
<li>Vælg en konto → Continue</li>
<li>Du lander på <span class="font-mono text-amber-300 text-xs">console.tink.com/callback<strong>?code=XXXX</strong></span> — kopier koden</li>
<li>Indsæt koden i feltet herunder og klik "Brug kode"</li>
</ol>
</div>
<div class="flex items-center gap-3">
<a href="{{ dev_tink_link_url }}" target="_blank"
class="inline-flex items-center gap-2 px-5 py-2.5 bg-emerald-600 hover:bg-emerald-500 text-white font-semibold rounded-lg transition">
Åbn Tink Link
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg>
</a>
<a href="/demo/reset"
class="inline-flex items-center gap-1.5 px-4 py-2.5 border border-slate-700 text-slate-400 hover:text-white hover:border-slate-500 rounded-lg text-sm transition">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
Start forfra
</a>
</div>
<!-- Code paste form -->
<form method="POST" action="/demo/step/3" class="flex gap-2 items-stretch pt-1 border-t border-slate-800">
<input type="text" name="code" placeholder="Indsæt code=XXXX her efter Tink Link flow..."
class="flex-1 bg-slate-800 border border-slate-700 text-slate-200 rounded-lg px-3 py-2 text-sm font-mono placeholder-slate-600 focus:outline-none focus:border-emerald-600" required>
<button type="submit"
class="px-4 py-2 bg-emerald-700 hover:bg-emerald-600 text-white text-sm font-semibold rounded-lg transition whitespace-nowrap">
Brug kode
</button>
</form>
</div>
<!-- SECONDARY: direct callback (only works when redirect URI is registered) -->
{% if tink_link_url %}
<details class="bg-slate-900 border border-slate-700/30 rounded-xl overflow-hidden">
<summary class="px-5 py-3 cursor-pointer text-slate-500 hover:text-slate-400 text-xs flex items-center gap-2 select-none">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
Direkte callback (kræver registreret redirect URI i Console)
<span class="ml-auto"></span>
</summary>
<div class="px-5 pb-4 pt-3 border-t border-slate-800">
<p class="text-slate-500 text-xs mb-3">Virker kun når <code class="text-slate-400">{{ tink_link_url | truncate(60) }}</code> er registreret som redirect URI i Tink Console.</p>
<a href="{{ tink_link_url }}"
class="inline-flex items-center gap-2 px-4 py-2 bg-slate-700 hover:bg-slate-600 text-slate-300 text-sm rounded-lg transition">
Åbn med direkte callback
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg>
</a>
</div>
</details>
{% endif %}
{% endif %}{# end not cb_success #}
{% endif %}{# end tink_link_url #}
<!-- Error state -->
{% if error %}
<div class="bg-red-950/50 border border-red-800/50 rounded-xl p-5">
<div class="flex items-start gap-3">
<span class="text-red-400 text-xl flex-shrink-0"></span>
<div>
<h3 class="text-red-300 font-semibold mb-1">Fejl</h3>
<pre class="text-red-400 text-sm font-mono whitespace-pre-wrap">{{ error }}</pre>
</div>
</div>
</div>
{% endif %}
<!-- JSON response -->
{% if result %}
<div class="bg-slate-900 border border-slate-800 rounded-xl overflow-hidden">
<div class="flex items-center justify-between px-4 py-3 border-b border-slate-800">
<div class="flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-emerald-400"></span>
<span class="text-sm text-slate-300 font-semibold">Response</span>
<span class="text-xs text-emerald-400 font-mono">200 OK</span>
{% if is_demo %}
<span class="text-xs px-2 py-0.5 rounded-full font-semibold bg-amber-900/60 text-amber-300 border border-amber-700/40">⚠ Sample Data</span>
{% endif %}
</div>
<button onclick="copyToClipboard('json-{{ step }}')"
class="text-xs text-slate-400 hover:text-white transition px-2 py-1 rounded bg-slate-800 hover:bg-slate-700">
Kopier JSON
</button>
</div>
<div class="p-4 max-h-[520px] overflow-y-auto">
<pre id="json-{{ step }}" class="raw-json">{{ result | tojson(indent=2) }}</pre>
</div>
</div>
{% elif not error %}
<!-- Waiting state -->
<div class="bg-slate-900 border border-slate-800 rounded-xl p-10 flex flex-col items-center justify-center gap-3 text-center">
<div class="w-12 h-12 rounded-full bg-slate-800 flex items-center justify-center">
<svg class="w-6 h-6 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
</div>
<p class="text-slate-400 text-sm">Klik på knappen ovenfor for at køre dette API-kald og se svaret her.</p>
</div>
{% endif %}
</div>
</div>
{% endblock %}