presseportale/resources/views/web/api.blade.php
Kevin Adametz d1939f6f2a Web-Frontend: Umbau Spokes/Hub, Kontakt-Widget (contact-launcher)
Startseiten/Feeds/Kategorie/Rechtsseiten ueberarbeitet, Kontakt-Modal durch
schwebendes contact-launcher-Widget ersetzt, legal-language-notice ergaenzt;
Platzhalter-SVGs + Theme-CSS angepasst.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 15:45:58 +00:00

242 lines
14 KiB
PHP

@extends('web.layouts.web-master')
@section('title', __('static.api.meta_title'))
@section('meta_description', __('static.api.meta_description'))
@php
// Die API läuft zentral über den Publisher-Hub (pressekonto).
$apiBase = rtrim((string) config('domains.domain_portal_url', config('app.url')), '/').'/api/v1';
$host = request()->getHost();
$apiBrandKey = str_contains($host, 'pressekonto')
? 'pressekonto'
: (str_contains($host, 'presseecho') ? 'presseecho' : 'businessportal24');
$apiContactEmail = config('domains.domains.'.$apiBrandKey.'.brand.contact_email') ?? 'info@businessportal24.com';
$endpoints = [
[
'group' => __('static.api.group_releases'),
'items' => [
['method' => 'GET', 'path' => '/press-releases', 'desc' => __('static.api.ep_pr_index'), 'ability' => 'press-releases:read'],
['method' => 'POST', 'path' => '/press-releases', 'desc' => __('static.api.ep_pr_store'), 'ability' => 'press-releases:write'],
['method' => 'GET', 'path' => '/press-releases/{id}', 'desc' => __('static.api.ep_pr_show'), 'ability' => 'press-releases:read'],
['method' => 'PATCH', 'path' => '/press-releases/{id}', 'desc' => __('static.api.ep_pr_update'), 'ability' => 'press-releases:write'],
['method' => 'POST', 'path' => '/press-releases/{id}/submit', 'desc' => __('static.api.ep_pr_submit'), 'ability' => 'press-releases:write'],
['method' => 'DELETE', 'path' => '/press-releases/{id}', 'desc' => __('static.api.ep_pr_destroy'), 'ability' => 'press-releases:write'],
],
],
[
'group' => __('static.api.group_images'),
'items' => [
['method' => 'GET', 'path' => '/press-releases/{id}/images', 'desc' => __('static.api.ep_img_index'), 'ability' => 'press-releases:read'],
['method' => 'POST', 'path' => '/press-releases/{id}/images', 'desc' => __('static.api.ep_img_store'), 'ability' => 'press-release-images:write'],
['method' => 'DELETE', 'path' => '/press-release-images/{imageId}', 'desc' => __('static.api.ep_img_destroy'), 'ability' => 'press-release-images:write'],
],
],
[
'group' => __('static.api.group_master_data'),
'items' => [
['method' => 'GET', 'path' => '/companies', 'desc' => __('static.api.ep_companies_index'), 'ability' => 'companies:read'],
['method' => 'GET', 'path' => '/companies/{id}', 'desc' => __('static.api.ep_companies_show'), 'ability' => 'companies:read'],
['method' => 'GET', 'path' => '/categories', 'desc' => __('static.api.ep_categories_index'), 'ability' => 'press-releases:read'],
],
],
];
$pressReleaseFields = [
['name' => 'company_id', 'type' => 'integer', 'required' => true, 'desc' => __('static.api.field_company_id')],
['name' => 'category_id', 'type' => 'integer', 'required' => true, 'desc' => __('static.api.field_category_id')],
['name' => 'language', 'type' => 'string', 'required' => true, 'desc' => __('static.api.field_language')],
['name' => 'title', 'type' => 'string', 'required' => true, 'desc' => __('static.api.field_title')],
['name' => 'text', 'type' => 'string', 'required' => true, 'desc' => __('static.api.field_text')],
['name' => 'backlink_url', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_backlink_url')],
['name' => 'keywords', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_keywords')],
['name' => 'teaser_begin / teaser_end', 'type' => 'integer', 'required' => false, 'desc' => __('static.api.field_teaser')],
['name' => 'no_export', 'type' => 'boolean', 'required' => false, 'desc' => __('static.api.field_no_export')],
];
$imageFields = [
['name' => 'image', 'type' => 'file', 'required' => true, 'desc' => __('static.api.field_image')],
['name' => 'title', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_image_title')],
['name' => 'description', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_image_description')],
['name' => 'copyright', 'type' => 'string', 'required' => false, 'desc' => __('static.api.field_image_copyright')],
['name' => 'is_preview', 'type' => 'boolean', 'required' => false, 'desc' => __('static.api.field_image_is_preview')],
];
$statusCodes = [
['code' => '200 / 201 / 204', 'desc' => __('static.api.status_2xx')],
['code' => '401', 'desc' => __('static.api.status_401')],
['code' => '402', 'desc' => __('static.api.status_402')],
['code' => '403', 'desc' => __('static.api.status_403')],
['code' => '409', 'desc' => __('static.api.status_409')],
['code' => '422', 'desc' => __('static.api.status_422')],
['code' => '429', 'desc' => __('static.api.status_429')],
];
$methodColors = [
'GET' => 'text-[#1F6B3F] bg-[#E7F2EA]',
'POST' => 'text-[#8A4B12] bg-[#F7EBDD]',
'PATCH' => 'text-[#6B4FA1] bg-[#EEE9F7]',
'DELETE' => 'text-[#A13030] bg-[#F7E5E5]',
];
@endphp
@section('content')
<x-web.static-page
:eyebrow="__('static.api.eyebrow')"
:title="__('static.api.title')"
:lead="__('static.api.lead')"
:breadcrumb="__('static.api.breadcrumb')"
>
{{-- Überblick + Authentifizierung --}}
<div class="pm-body max-w-[760px]">
<h2>{{ __('static.api.basics_heading') }}</h2>
<p>{!! __('static.api.basics_text', ['base' => e($apiBase)]) !!}</p>
<h3>{{ __('static.api.auth_heading') }}</h3>
<p>{!! __('static.api.auth_text') !!}</p>
</div>
{{-- Endpunkte --}}
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.endpoints_heading') }}</h2>
<div class="max-w-[900px] space-y-8">
@foreach ($endpoints as $group)
<div>
<h3 class="text-[14px] font-semibold text-ink m-0 mb-3">{{ $group['group'] }}</h3>
<div class="border border-bg-rule divide-y divide-bg-rule">
@foreach ($group['items'] as $endpoint)
<div class="px-5 py-3.5 grid gap-x-4 gap-y-1 sm:grid-cols-[64px_1fr] items-baseline">
<span class="inline-flex justify-center px-1.5 py-0.5 text-[11px] font-bold tracking-wide rounded-[2px] {{ $methodColors[$endpoint['method']] ?? 'text-ink bg-bg-elev' }}">{{ $endpoint['method'] }}</span>
<div>
<code class="font-mono text-[13px] text-ink">{{ $endpoint['path'] }}</code>
<p class="text-[12.5px] leading-[1.55] text-ink-2 mt-1 mb-0">
{{ $endpoint['desc'] }}
<span class="text-ink-4">· {{ __('static.api.permission') }}: <code class="font-mono text-[11.5px]">{{ $endpoint['ability'] }}</code></span>
</p>
</div>
</div>
@endforeach
</div>
</div>
@endforeach
</div>
{{-- Felder --}}
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.fields_pr_heading') }}</h2>
<div class="max-w-[900px] border border-bg-rule overflow-x-auto">
<table class="w-full text-[13px] border-collapse">
<thead>
<tr class="text-left text-ink-3 bg-bg-elev border-b border-bg-rule">
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_field') }}</th>
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_type') }}</th>
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_required') }}</th>
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_description') }}</th>
</tr>
</thead>
<tbody class="divide-y divide-bg-rule">
@foreach ($pressReleaseFields as $field)
<tr>
<td class="px-4 py-2.5 font-mono text-[12.5px] text-ink whitespace-nowrap">{{ $field['name'] }}</td>
<td class="px-4 py-2.5 text-ink-3">{{ $field['type'] }}</td>
<td class="px-4 py-2.5 text-ink-3">{{ $field['required'] ? __('static.api.required_yes') : '—' }}</td>
<td class="px-4 py-2.5 text-ink-2">{{ $field['desc'] }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-12 mb-4">{{ __('static.api.fields_img_heading') }}</h2>
<div class="max-w-[900px] border border-bg-rule overflow-x-auto">
<table class="w-full text-[13px] border-collapse">
<thead>
<tr class="text-left text-ink-3 bg-bg-elev border-b border-bg-rule">
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_field') }}</th>
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_type') }}</th>
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_required') }}</th>
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_description') }}</th>
</tr>
</thead>
<tbody class="divide-y divide-bg-rule">
@foreach ($imageFields as $field)
<tr>
<td class="px-4 py-2.5 font-mono text-[12.5px] text-ink whitespace-nowrap">{{ $field['name'] }}</td>
<td class="px-4 py-2.5 text-ink-3">{{ $field['type'] }}</td>
<td class="px-4 py-2.5 text-ink-3">{{ $field['required'] ? __('static.api.required_yes') : '—' }}</td>
<td class="px-4 py-2.5 text-ink-2">{{ $field['desc'] }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
{{-- Workflow-Beispiel --}}
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.quickstart_heading') }}</h2>
<p class="text-[13px] text-ink-2 m-0 mb-4 max-w-[640px]">{{ __('static.api.quickstart_text') }}</p>
<div class="max-w-[900px] bg-[#16140f] border border-bg-rule-strong rounded-[3px] p-5 overflow-x-auto">
<pre class="text-[12.5px] leading-[1.6] font-mono text-[#9ad1a5] m-0"><code>{{ __('static.api.quickstart_step_1') }}
curl -X POST {{ $apiBase }}/press-releases \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"company_id": 1,
"category_id": 2,
"language": "de",
"title": "Neue Produktankündigung",
"text": "&lt;p&gt;Unser neues Produkt …&lt;/p&gt;"
}'
{{ __('static.api.quickstart_step_2') }}
curl -X POST {{ $apiBase }}/press-releases/123/images \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-F "image=@pressefoto.jpg" \
-F "copyright=Mustermann GmbH" \
-F "is_preview=1"
{{ __('static.api.quickstart_step_3') }}
curl -X POST {{ $apiBase }}/press-releases/123/submit \
-H "Authorization: Bearer YOUR_API_TOKEN"</code></pre>
</div>
<p class="text-[12px] text-ink-3 m-0 mt-3">
{{ __('static.api.openapi_note') }} <a href="{{ route('docs.api.v1') }}" class="text-brand hover:underline">{{ __('static.api.openapi_link') }}</a>.
</p>
{{-- Statuscodes --}}
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">{{ __('static.api.status_heading') }}</h2>
<div class="max-w-[900px] border border-bg-rule overflow-x-auto">
<table class="w-full text-[13px] border-collapse">
<thead>
<tr class="text-left text-ink-3 bg-bg-elev border-b border-bg-rule">
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_code') }}</th>
<th class="font-medium px-4 py-2.5">{{ __('static.api.th_meaning') }}</th>
</tr>
</thead>
<tbody class="divide-y divide-bg-rule">
@foreach ($statusCodes as $status)
<tr>
<td class="px-4 py-2.5 font-mono text-[12.5px] text-ink whitespace-nowrap">{{ $status['code'] }}</td>
<td class="px-4 py-2.5 text-ink-2">{{ $status['desc'] }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
{{-- CTA --}}
<div class="mt-14 border border-bg-rule bg-bg-elev p-6 sm:p-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-5 max-w-[900px]">
<div>
<h2 class="font-serif text-[20px] font-semibold tracking-[-0.3px] text-ink m-0">{{ __('static.api.cta_heading') }}</h2>
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">{{ __('static.api.cta_text') }} <a href="mailto:{{ $apiContactEmail }}" class="text-brand hover:underline">{{ $apiContactEmail }}</a></p>
</div>
<div class="flex flex-wrap gap-3 flex-shrink-0">
<a href="{{ rtrim((string) config('domains.domain_portal_url', config('app.url')), '/') }}/login"
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-white bg-brand hover:bg-brand-deep rounded-[2px] transition-colors">
{{ __('static.api.cta_account') }}
</a>
<a href="{{ route('preise') }}"
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-ink border border-bg-rule-strong hover:bg-bg transition-colors rounded-[2px]">
{{ __('static.api.cta_pricing') }}
</a>
</div>
</div>
</x-web.static-page>
@endsection