1a12fb870b
- New /developers/ page with API docs, SDKs, pricing, use cases - OpenAPI 3.0 spec for Orders, Missions, Photos, Analytics - Case study: Glasskiosken i Flatenbadet — complete ROI analysis - Updated /order/ with recurring missions and frequency dropdown
493 lines
13 KiB
HTML
493 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
<title>quiXzoom Frilans Payout</title>
|
|
<link rel="stylesheet" href="/_design-system/apple-native/tokens.css">
|
|
<link rel="stylesheet" href="/_design-system/apple-native/components.css">
|
|
<style>
|
|
/* Apple iPhone Native Styles */
|
|
:root {
|
|
--ios-blue: #007AFF;
|
|
--ios-green: #34C759;
|
|
--ios-red: #FF3B30;
|
|
--ios-gray6: #F2F2F7;
|
|
--ios-gray5: #E5E5EA;
|
|
--label-primary: #000000;
|
|
--label-secondary: rgba(60,60,67,0.6);
|
|
--label-tertiary: rgba(60,60,67,0.3);
|
|
--system-background: #FFFFFF;
|
|
--secondary-system-background: #F2F2F7;
|
|
--separator: #C6C6C8;
|
|
--ios-radius: 13px;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--label-primary: #FFFFFF;
|
|
--label-secondary: rgba(235,235,245,0.6);
|
|
--system-background: #000000;
|
|
--secondary-system-background: #1C1C1E;
|
|
--separator: #38383A;
|
|
}
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', system-ui, sans-serif;
|
|
background: var(--ios-gray6);
|
|
color: var(--label-primary);
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
.container {
|
|
max-width: 430px;
|
|
margin: 0 auto;
|
|
padding: 16px;
|
|
padding-top: max(16px, env(safe-area-inset-top));
|
|
padding-bottom: max(16px, env(safe-area-inset-bottom));
|
|
}
|
|
|
|
/* Header */
|
|
.header {
|
|
background: linear-gradient(135deg, var(--ios-blue), #5856D6);
|
|
border-radius: var(--ios-radius);
|
|
padding: 24px;
|
|
color: white;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.header h1 {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.header p {
|
|
opacity: 0.8;
|
|
font-size: 15px;
|
|
}
|
|
|
|
/* Cards */
|
|
.card {
|
|
background: var(--system-background);
|
|
border-radius: var(--ios-radius);
|
|
margin-bottom: 12px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.card-header {
|
|
padding: 16px;
|
|
border-bottom: 0.5px solid var(--separator);
|
|
}
|
|
|
|
.card-header h2 {
|
|
font-size: 20px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.card-body {
|
|
padding: 16px;
|
|
}
|
|
|
|
/* Market Grid */
|
|
.market-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 8px;
|
|
}
|
|
|
|
.market-btn {
|
|
aspect-ratio: 1;
|
|
border: 2px solid var(--ios-gray5);
|
|
border-radius: var(--ios-radius);
|
|
background: var(--system-background);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
transition: all 0.2s cubic-bezier(0.32, 0.72, 0, 1);
|
|
}
|
|
|
|
.market-btn:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.market-btn.selected {
|
|
border-color: var(--ios-blue);
|
|
background: rgba(0,122,255,0.1);
|
|
}
|
|
|
|
.market-btn .flag {
|
|
font-size: 32px;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.market-btn .code {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--label-primary);
|
|
}
|
|
|
|
/* Options */
|
|
.option {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 16px;
|
|
border-bottom: 0.5px solid var(--separator);
|
|
cursor: pointer;
|
|
transition: background 0.2s;
|
|
}
|
|
|
|
.option:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.option:active {
|
|
background: var(--ios-gray5);
|
|
}
|
|
|
|
.option-icon {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-right: 12px;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.option-content {
|
|
flex: 1;
|
|
}
|
|
|
|
.option-title {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.option-desc {
|
|
font-size: 13px;
|
|
color: var(--label-secondary);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.option-check {
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 50%;
|
|
border: 2px solid var(--separator);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.option.selected .option-check {
|
|
background: var(--ios-blue);
|
|
border-color: var(--ios-blue);
|
|
}
|
|
|
|
.option.selected .option-check::after {
|
|
content: '✓';
|
|
color: white;
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* Calculator */
|
|
.calc-input {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.calc-input input {
|
|
flex: 1;
|
|
padding: 16px;
|
|
border: 1px solid var(--separator);
|
|
border-radius: 10px;
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
background: var(--system-background);
|
|
color: var(--label-primary);
|
|
}
|
|
|
|
.calc-btn {
|
|
padding: 16px 24px;
|
|
background: var(--ios-blue);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 10px;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Breakdown */
|
|
.breakdown-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 12px 0;
|
|
border-bottom: 0.5px solid var(--separator);
|
|
}
|
|
|
|
.breakdown-row:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.breakdown-row.net {
|
|
font-weight: 600;
|
|
color: var(--ios-green);
|
|
}
|
|
|
|
.breakdown-row.fee {
|
|
color: var(--ios-red);
|
|
}
|
|
|
|
/* Primary Button */
|
|
.btn-primary {
|
|
width: 100%;
|
|
padding: 18px;
|
|
background: var(--ios-blue);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 12px;
|
|
font-size: 17px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
margin-top: 16px;
|
|
transition: opacity 0.2s;
|
|
}
|
|
|
|
.btn-primary:active {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* Info Box */
|
|
.info-box {
|
|
background: rgba(0,122,255,0.08);
|
|
border-radius: 10px;
|
|
padding: 16px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.info-box p {
|
|
font-size: 13px;
|
|
color: var(--label-secondary);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
/* Spring physics for all transitions */
|
|
* {
|
|
transition-timing-function: cubic-bezier(0.32, 0.72, 0, 1);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<!-- Header -->
|
|
<div class="header">
|
|
<h1>Frilans Payout</h1>
|
|
<p>Get paid without a company</p>
|
|
</div>
|
|
|
|
<!-- Market Selection -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>Select Market</h2>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="market-grid">
|
|
<button class="market-btn selected" onclick="selectMarket('SE')">
|
|
<span class="flag">🇸🇪</span>
|
|
<span class="code">SE</span>
|
|
</button>
|
|
<button class="market-btn" onclick="selectMarket('NO')">
|
|
<span class="flag">🇳🇴</span>
|
|
<span class="code">NO</span>
|
|
</button>
|
|
<button class="market-btn" onclick="selectMarket('DK')">
|
|
<span class="flag">🇩🇰</span>
|
|
<span class="code">DK</span>
|
|
</button>
|
|
<button class="market-btn" onclick="selectMarket('FI')">
|
|
<span class="flag">🇫🇮</span>
|
|
<span class="code">FI</span>
|
|
</button>
|
|
<button class="market-btn" onclick="selectMarket('DE')">
|
|
<span class="flag">🇩🇪</span>
|
|
<span class="code">DE</span>
|
|
</button>
|
|
<button class="market-btn" onclick="selectMarket('NL')">
|
|
<span class="flag">🇳🇱</span>
|
|
<span class="code">NL</span>
|
|
</button>
|
|
<button class="market-btn" onclick="selectMarket('US')">
|
|
<span class="flag">🇺🇸</span>
|
|
<span class="code">US</span>
|
|
</button>
|
|
<button class="market-btn" onclick="selectMarket('GB')">
|
|
<span class="flag">🇬🇧</span>
|
|
<span class="code">GB</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tax Handling -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>Tax Handling</h2>
|
|
</div>
|
|
<div class="card-body" style="padding: 0;">
|
|
<div class="option selected" onclick="selectTax('platform')">
|
|
<div class="option-icon" style="background: rgba(0,122,255,0.1);">🏢</div>
|
|
<div class="option-content">
|
|
<div class="option-title">quiXzoom handles tax</div>
|
|
<div class="option-desc">We withhold tax and send KU10</div>
|
|
</div>
|
|
<div class="option-check"></div>
|
|
</div>
|
|
<div class="option" onclick="selectTax('self')">
|
|
<div class="option-icon" style="background: rgba(255,149,0,0.1);">📄</div>
|
|
<div class="option-content">
|
|
<div class="option-title">I handle tax myself</div>
|
|
<div class="option-desc">You declare and pay tax yourself</div>
|
|
</div>
|
|
<div class="option-check"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Payout Method -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>Payout Method</h2>
|
|
</div>
|
|
<div class="card-body" style="padding: 0;">
|
|
<div class="option selected" onclick="selectMethod('frilans')">
|
|
<div class="option-icon" style="background: rgba(52,199,89,0.1);">💳</div>
|
|
<div class="option-content">
|
|
<div class="option-title">quiXzoom Frilans</div>
|
|
<div class="option-desc">Direct to account • Weekly</div>
|
|
</div>
|
|
<div class="option-check"></div>
|
|
</div>
|
|
<div class="option" onclick="selectMethod('stripe')">
|
|
<div class="option-icon" style="background: rgba(88,86,214,0.1);">⚡</div>
|
|
<div class="option-content">
|
|
<div class="option-title">Stripe Connect</div>
|
|
<div class="option-desc">Fastest • 1-2 days</div>
|
|
</div>
|
|
<div class="option-check"></div>
|
|
</div>
|
|
<div class="option" onclick="selectMethod('bank')">
|
|
<div class="option-icon" style="background: rgba(175,82,222,0.1);">🏦</div>
|
|
<div class="option-content">
|
|
<div class="option-title">Bank Transfer</div>
|
|
<div class="option-desc">Traditional • 3-5 days</div>
|
|
</div>
|
|
<div class="option-check"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Calculator -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>Calculator</h2>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="calc-input">
|
|
<input type="number" id="calcAmount" value="1000" placeholder="Amount">
|
|
<button class="calc-btn" onclick="calculate()">Calculate</button>
|
|
</div>
|
|
|
|
<div id="breakdown" style="display: none;">
|
|
<div class="breakdown-row">
|
|
<span>Gross</span>
|
|
<span id="gross">1,000 kr</span>
|
|
</div>
|
|
<div class="breakdown-row fee">
|
|
<span>Platform (15%)</span>
|
|
<span>-150 kr</span>
|
|
</div>
|
|
<div class="breakdown-row fee">
|
|
<span>Processing (6%)</span>
|
|
<span>-60 kr</span>
|
|
</div>
|
|
<div class="breakdown-row fee">
|
|
<span>Tax (30%)</span>
|
|
<span>-237 kr</span>
|
|
</div>
|
|
<div class="breakdown-row net">
|
|
<span>Net to you</span>
|
|
<span id="net">553 kr</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Save Button -->
|
|
<button class="btn-primary" onclick="saveSettings()">Save Settings</button>
|
|
</div>
|
|
|
|
<script>
|
|
// State
|
|
let state = {
|
|
market: 'SE',
|
|
taxHandling: 'platform',
|
|
payoutMethod: 'frilans'
|
|
};
|
|
|
|
function selectMarket(code) {
|
|
state.market = code;
|
|
document.querySelectorAll('.market-btn').forEach(btn => {
|
|
btn.classList.toggle('selected', btn.querySelector('.code').textContent === code);
|
|
});
|
|
}
|
|
|
|
function selectTax(handling) {
|
|
state.taxHandling = handling;
|
|
document.querySelectorAll('.option').forEach((opt, i) => {
|
|
if (i < 2) opt.classList.toggle('selected', i === (handling === 'platform' ? 0 : 1));
|
|
});
|
|
}
|
|
|
|
function selectMethod(method) {
|
|
state.payoutMethod = method;
|
|
const methods = ['frilans', 'stripe', 'bank'];
|
|
document.querySelectorAll('.option').forEach((opt, i) => {
|
|
if (i >= 2) opt.classList.toggle('selected', methods[i-2] === method);
|
|
});
|
|
}
|
|
|
|
function calculate() {
|
|
const amount = parseInt(document.getElementById('calcAmount').value) || 0;
|
|
const platformFee = Math.round(amount * 0.15);
|
|
const processingFee = Math.round(amount * 0.06);
|
|
const taxAmount = state.taxHandling === 'platform' ? Math.round((amount - platformFee) * 0.30) : 0;
|
|
const net = amount - platformFee - processingFee - taxAmount;
|
|
|
|
document.getElementById('gross').textContent = amount.toLocaleString() + ' kr';
|
|
document.getElementById('net').textContent = net.toLocaleString() + ' kr';
|
|
document.getElementById('breakdown').style.display = 'block';
|
|
}
|
|
|
|
function saveSettings() {
|
|
alert('Settings saved!\n\nMarket: ' + state.market + '\nTax: ' + state.taxHandling + '\nMethod: ' + state.payoutMethod);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|