115 lines
13 KiB
PHP
115 lines
13 KiB
PHP
@extends('layouts.app')
|
|
@section('title', 'Settings')
|
|
@section('content')
|
|
<div>
|
|
<p class="text-xs font-bold uppercase tracking-[.2em] text-brand">Integrations</p>
|
|
<h2 class="mt-2 text-2xl font-bold">Integration settings</h2>
|
|
<p class="mt-1 text-sm text-slate-400">Manage the connections used by your shop and workshop. Saved values are encrypted in the database.</p>
|
|
</div>
|
|
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900 p-6">
|
|
<div class="flex flex-wrap items-center justify-between gap-3">
|
|
<div>
|
|
<h3 class="text-lg font-semibold">Etsy shop</h3>
|
|
<p class="mt-1 text-sm text-slate-400">{{ $storedCredentials ? 'Credentials saved in the database.' : ($configured ? 'Using server credentials. Save them here to manage them in the dashboard.' : 'No credentials saved yet.') }}</p>
|
|
</div>
|
|
<span class="rounded-full px-3 py-1 text-xs font-semibold {{ $configured ? 'bg-emerald-500/10 text-emerald-300' : 'bg-amber-500/10 text-amber-200' }}">{{ $configured ? 'Configured' : 'Setup needed' }}</span>
|
|
</div>
|
|
|
|
<form method="post" action="{{ route('settings.etsy.update') }}" class="mt-6 grid gap-5 md:grid-cols-2">
|
|
@csrf
|
|
@method('PUT')
|
|
<label class="grid gap-2 text-sm text-slate-300">
|
|
Etsy app keystring
|
|
<input name="keystring" type="password" autocomplete="new-password" maxlength="255" placeholder="{{ $configured ? 'Leave blank to keep current key' : 'Enter your app keystring' }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100 placeholder:text-slate-500" {{ $configured ? '' : 'required' }}>
|
|
</label>
|
|
<label class="grid gap-2 text-sm text-slate-300">
|
|
Etsy shared secret
|
|
<input name="shared_secret" type="password" autocomplete="new-password" maxlength="255" placeholder="{{ $configured ? 'Leave blank to keep current secret' : 'Enter your shared secret' }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100 placeholder:text-slate-500" {{ $configured ? '' : 'required' }}>
|
|
</label>
|
|
<label class="grid gap-2 text-sm text-slate-300">
|
|
Shop name
|
|
<input name="shop_name" type="text" maxlength="255" value="{{ old('shop_name', $shopName) }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100">
|
|
</label>
|
|
<label class="grid gap-2 text-sm text-slate-300">
|
|
OAuth callback URL
|
|
<input name="redirect_uri" type="url" maxlength="2048" value="{{ old('redirect_uri', $redirectUri) }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100">
|
|
</label>
|
|
<div class="md:col-span-2">
|
|
<button class="rounded-xl bg-brand px-5 py-3 text-sm font-semibold text-slate-950 hover:bg-brand/90">Save credentials</button>
|
|
</div>
|
|
</form>
|
|
<p class="mt-4 text-xs text-slate-500">Blank credential fields keep the current values. Saving imports any server credentials you have not entered here. Changing the app key disconnects the current Etsy shop. The callback must match the URL registered with Etsy.</p>
|
|
</section>
|
|
|
|
<div class="grid gap-5 xl:grid-cols-2">
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900 p-6">
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div><h3 class="text-lg font-semibold">Parcel2Go</h3><p class="mt-1 text-sm text-slate-400">Quotes, labels, shipments and collections.</p></div>
|
|
<span @class(['rounded-full px-3 py-1 text-xs font-semibold', 'bg-emerald-500/10 text-emerald-300' => $integrations['parcel2go']['configured'], 'bg-amber-500/10 text-amber-200' => ! $integrations['parcel2go']['configured']])>{{ $integrations['parcel2go']['configured'] ? 'Configured' : 'Setup needed' }}</span>
|
|
</div>
|
|
<p class="mt-3 text-xs text-slate-500">{{ $integrations['parcel2go']['stored'] ? 'Saved in the database.' : 'Using server values where available. Save to import them.' }}</p>
|
|
<form method="post" action="{{ route('settings.integrations.update', 'parcel2go') }}" class="mt-5 grid gap-4">
|
|
@csrf @method('PUT')
|
|
<label class="grid gap-2 text-sm text-slate-300">Client ID<input name="client_id" type="password" autocomplete="new-password" maxlength="255" placeholder="Leave blank to keep current value" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100 placeholder:text-slate-500"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">Client secret<input name="client_secret" type="password" autocomplete="new-password" maxlength="255" placeholder="Leave blank to keep current value" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100 placeholder:text-slate-500"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">OAuth token URL<input name="auth_url" type="url" maxlength="2048" value="{{ old('auth_url', $integrations['parcel2go']['auth_url']) }}" placeholder="https://…" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">API base URL<input name="base_url" type="url" maxlength="2048" value="{{ old('base_url', $integrations['parcel2go']['base_url']) }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">Collection postcode<input name="collection_postcode" maxlength="12" value="{{ old('collection_postcode', $integrations['parcel2go']['collection_postcode']) }}" placeholder="Used for Etsy order shipping quotes" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">Authorization Code Client ID<input name="profile_client_id" type="password" autocomplete="new-password" maxlength="255" placeholder="{{ $integrations['parcel2go']['profile_client_configured'] ? 'Saved — leave blank to keep it' : 'Enter the new Authorization Code Client ID' }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100 placeholder:text-slate-500"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">API access
|
|
<select name="scope" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100">
|
|
@foreach(['public-api' => 'Shipping quotes and collections', 'public-api my-profile' => 'Shipping and account history', 'public-api payment' => 'Shipping and PrePay payments', 'public-api payment my-profile' => 'Shipping, account history and PrePay'] as $scope => $label)
|
|
<option value="{{ $scope }}" @selected(old('scope', $integrations['parcel2go']['scope']) === $scope)>{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</label>
|
|
<p class="text-xs text-slate-500">Keep basic <code>public-api</code> access for quotes and bookings. The separate Authorization Code client connects your own account for shipment history and labels.</p>
|
|
<button class="w-fit rounded-xl bg-brand px-5 py-3 text-sm font-semibold text-slate-950 hover:bg-brand/90">Save Parcel2Go</button>
|
|
</form>
|
|
<div class="mt-5 grid gap-3 rounded-xl border border-slate-700 bg-slate-950 p-4 text-sm">
|
|
<div class="flex flex-wrap items-center justify-between gap-2"><p class="font-semibold">Parcel2Go account consent</p><span @class(['rounded-full px-2 py-1 text-xs font-semibold', 'bg-emerald-500/10 text-emerald-300' => $integrations['parcel2go']['profile_connected'], 'bg-amber-500/10 text-amber-200' => ! $integrations['parcel2go']['profile_connected']])>{{ $integrations['parcel2go']['profile_connected'] ? 'Connected' : 'Not connected' }}</span></div>
|
|
<p class="text-slate-400">Create an <strong>Authorization Code</strong> client in Parcel2Go. Set Application URL to <code>{{ url('/') }}</code> and Redirect URI to this exact address:</p>
|
|
<code class="overflow-x-auto rounded-lg border border-slate-700 bg-slate-900 px-3 py-2 text-slate-200">{{ $integrations['parcel2go']['callback_url'] }}</code>
|
|
<p class="text-slate-400">Save its Client ID above, then sign in and approve <code>my-profile</code> access. The account tokens are encrypted in the database. If Parcel2Go does not issue a refresh token, reconnect when access expires. If consent rejects this scope, contact <a class="text-brand hover:underline" href="mailto:apihelp@parcel2go.com">apihelp@parcel2go.com</a>.</p>
|
|
@if($integrations['parcel2go']['profile_client_configured'])<form method="post" action="{{ route('parcel2go.connect') }}">@csrf<button class="rounded-xl border border-brand/40 px-4 py-2 font-semibold text-brand hover:bg-brand/10">{{ $integrations['parcel2go']['profile_connected'] ? 'Reconnect Parcel2Go account' : 'Connect Parcel2Go account' }}</button></form>@endif
|
|
</div>
|
|
</section>
|
|
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900 p-6">
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div><h3 class="text-lg font-semibold">BamBuddy</h3><p class="mt-1 text-sm text-slate-400">Live print farm data.</p></div>
|
|
<span @class(['rounded-full px-3 py-1 text-xs font-semibold', 'bg-emerald-500/10 text-emerald-300' => $integrations['bambuddy']['configured'], 'bg-amber-500/10 text-amber-200' => ! $integrations['bambuddy']['configured']])>{{ $integrations['bambuddy']['configured'] ? 'Configured' : 'Setup needed' }}</span>
|
|
</div>
|
|
<p class="mt-3 text-xs text-slate-500">{{ $integrations['bambuddy']['stored'] ? 'Saved in the database.' : 'Using server values where available. Save to import them.' }}</p>
|
|
<form method="post" action="{{ route('settings.integrations.update', 'bambuddy') }}" class="mt-5 grid gap-4">
|
|
@csrf @method('PUT')
|
|
<label class="grid gap-2 text-sm text-slate-300">BamBuddy URL<input name="url" type="url" maxlength="2048" value="{{ old('url', $integrations['bambuddy']['url']) }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">API key<input name="api_key" type="password" autocomplete="new-password" maxlength="512" placeholder="Leave blank to keep current value" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100 placeholder:text-slate-500"></label>
|
|
<button class="w-fit rounded-xl bg-brand px-5 py-3 text-sm font-semibold text-slate-950 hover:bg-brand/90">Save BamBuddy</button>
|
|
</form>
|
|
</section>
|
|
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900 p-6">
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div><h3 class="text-lg font-semibold">Filament dryer</h3><p class="mt-1 text-sm text-slate-400">Status, cycles and fault controls.</p></div>
|
|
<span @class(['rounded-full px-3 py-1 text-xs font-semibold', 'bg-emerald-500/10 text-emerald-300' => $integrations['dryer']['configured'], 'bg-amber-500/10 text-amber-200' => ! $integrations['dryer']['configured']])>{{ $integrations['dryer']['configured'] ? 'Configured' : 'Setup needed' }}</span>
|
|
</div>
|
|
<p class="mt-3 text-xs text-slate-500">{{ $integrations['dryer']['stored'] ? 'Saved in the database.' : 'Using server values where available. Save to import them.' }}</p>
|
|
<form method="post" action="{{ route('settings.integrations.update', 'dryer') }}" class="mt-5 grid gap-4">
|
|
@csrf @method('PUT')
|
|
<label class="grid gap-2 text-sm text-slate-300">Dryer API URL<input name="url" type="url" maxlength="2048" value="{{ old('url', $integrations['dryer']['url']) }}" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100"></label>
|
|
<label class="grid gap-2 text-sm text-slate-300">API key<input name="api_key" type="password" autocomplete="new-password" maxlength="512" placeholder="Leave blank to keep current value" class="rounded-xl border border-slate-700 bg-slate-950 px-4 py-3 text-slate-100 placeholder:text-slate-500"></label>
|
|
<button class="w-fit rounded-xl bg-brand px-5 py-3 text-sm font-semibold text-slate-950 hover:bg-brand/90">Save dryer</button>
|
|
</form>
|
|
</section>
|
|
</div>
|
|
|
|
<section class="rounded-2xl border border-slate-800 bg-slate-900 p-6">
|
|
<h3 class="text-lg font-semibold">OAuth callback</h3>
|
|
<p class="mt-1 text-sm text-slate-400">Register this exact HTTPS URL in your Etsy developer app.</p>
|
|
<code class="mt-4 block overflow-x-auto rounded-xl border border-slate-800 bg-slate-950 px-4 py-3 text-sm text-slate-200">{{ $redirectUri }}</code>
|
|
@if($configured)<a href="{{ route('etsy.index') }}" class="mt-5 inline-flex rounded-xl border border-slate-700 px-4 py-3 text-sm font-semibold text-slate-200 hover:border-brand hover:text-white">Go to Etsy shop</a>@endif
|
|
</section>
|
|
@endsection
|