547 lines
31 KiB
PHP
547 lines
31 KiB
PHP
|
|
<div class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||
|
|
<div class="max-w-lg w-full bg-white rounded-lg shadow-md p-8">
|
||
|
|
|
||
|
|
{{-- Step 1: Welcome --}}
|
||
|
|
@if ($step === 1)
|
||
|
|
<div class="text-center">
|
||
|
|
<h1 class="text-3xl font-bold text-gray-900 mb-2">Welcome to FFR</h1>
|
||
|
|
<p class="text-gray-600 mb-8">
|
||
|
|
Let's get you set up! We'll help you configure your Lemmy account, add your first feed, and create a channel for posting.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<div class="space-y-4 text-left">
|
||
|
|
<div class="flex items-center text-sm text-gray-600">
|
||
|
|
<div class="w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center mr-3 text-xs font-semibold">1</div>
|
||
|
|
<span>Connect your Lemmy account</span>
|
||
|
|
</div>
|
||
|
|
<div class="flex items-center text-sm text-gray-600">
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center mr-3 text-xs font-semibold">2</div>
|
||
|
|
<span>Add your first feed</span>
|
||
|
|
</div>
|
||
|
|
<div class="flex items-center text-sm text-gray-600">
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center mr-3 text-xs font-semibold">3</div>
|
||
|
|
<span>Configure a channel</span>
|
||
|
|
</div>
|
||
|
|
<div class="flex items-center text-sm text-gray-600">
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center mr-3 text-xs font-semibold">4</div>
|
||
|
|
<span>Create a route</span>
|
||
|
|
</div>
|
||
|
|
<div class="flex items-center text-sm text-gray-600">
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center mr-3 text-xs font-semibold">5</div>
|
||
|
|
<span>You're ready to go!</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="mt-8">
|
||
|
|
<button
|
||
|
|
wire:click="nextStep"
|
||
|
|
class="w-full bg-blue-600 text-white py-3 px-4 rounded-md hover:bg-blue-700 transition duration-200"
|
||
|
|
>
|
||
|
|
Get Started
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- Step 2: Platform Account --}}
|
||
|
|
@if ($step === 2)
|
||
|
|
<div class="text-center mb-8">
|
||
|
|
<h1 class="text-2xl font-bold text-gray-900 mb-2">Connect Your Lemmy Account</h1>
|
||
|
|
<p class="text-gray-600">
|
||
|
|
{{ $existingAccount ? 'Your connected Lemmy account' : 'Enter your Lemmy instance details and login credentials' }}
|
||
|
|
</p>
|
||
|
|
|
||
|
|
{{-- Progress indicator --}}
|
||
|
|
<div class="flex justify-center mt-6 space-x-2">
|
||
|
|
<div class="w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">1</div>
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold">2</div>
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold">3</div>
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold">4</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
@if (!empty($errors['general']))
|
||
|
|
<div class="p-3 bg-red-50 border border-red-200 rounded-md mt-6">
|
||
|
|
<p class="text-red-600 text-sm">{{ $errors['general'] }}</p>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
@if ($existingAccount)
|
||
|
|
{{-- Account Card --}}
|
||
|
|
<div class="mt-8">
|
||
|
|
<div class="bg-green-50 border border-green-200 rounded-lg p-6 text-left">
|
||
|
|
<div class="flex items-start justify-between">
|
||
|
|
<div class="flex items-center">
|
||
|
|
<div class="w-12 h-12 bg-green-500 text-white rounded-full flex items-center justify-center">
|
||
|
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
<div class="ml-4">
|
||
|
|
<h3 class="text-lg font-semibold text-gray-900">Account Connected</h3>
|
||
|
|
<div class="text-sm text-gray-600 mt-1">
|
||
|
|
<p><strong>Username:</strong> {{ $existingAccount['username'] }}</p>
|
||
|
|
<p><strong>Instance:</strong> {{ str_replace('https://', '', $existingAccount['instance_url']) }}</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<button
|
||
|
|
wire:click="deleteAccount"
|
||
|
|
wire:confirm="Are you sure you want to remove this account? You will need to re-enter your credentials."
|
||
|
|
class="text-red-600 hover:text-red-800 p-2"
|
||
|
|
title="Remove account"
|
||
|
|
>
|
||
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||
|
|
</svg>
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="flex justify-between mt-6">
|
||
|
|
<button wire:click="previousStep" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition duration-200">
|
||
|
|
← Back
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
wire:click="continueWithExistingAccount"
|
||
|
|
class="bg-blue-600 text-white py-2 px-6 rounded-md hover:bg-blue-700 transition duration-200"
|
||
|
|
>
|
||
|
|
Continue
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
@else
|
||
|
|
{{-- Login Form --}}
|
||
|
|
<form wire:submit="createPlatformAccount" class="space-y-6 mt-8 text-left">
|
||
|
|
<div>
|
||
|
|
<label for="instanceUrl" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Lemmy Instance Domain
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
id="instanceUrl"
|
||
|
|
wire:model="instanceUrl"
|
||
|
|
placeholder="lemmy.world"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<p class="text-sm text-gray-500 mt-1">Enter just the domain name (e.g., lemmy.world, belgae.social)</p>
|
||
|
|
@error('instanceUrl') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="username" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Username
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
id="username"
|
||
|
|
wire:model="username"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
@error('username') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="password" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Password
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="password"
|
||
|
|
id="password"
|
||
|
|
wire:model="password"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
@error('password') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="flex justify-between">
|
||
|
|
<button type="button" wire:click="previousStep" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition duration-200">
|
||
|
|
← Back
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
type="submit"
|
||
|
|
@disabled($isLoading)
|
||
|
|
class="bg-blue-600 text-white py-2 px-6 rounded-md hover:bg-blue-700 transition duration-200 disabled:opacity-50"
|
||
|
|
>
|
||
|
|
{{ $isLoading ? 'Connecting...' : 'Continue' }}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
@endif
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- Step 3: Feed --}}
|
||
|
|
@if ($step === 3)
|
||
|
|
<div class="text-center mb-8">
|
||
|
|
<h1 class="text-2xl font-bold text-gray-900 mb-2">Add Your First Feed</h1>
|
||
|
|
<p class="text-gray-600">
|
||
|
|
Choose from our supported news providers to monitor for new articles
|
||
|
|
</p>
|
||
|
|
|
||
|
|
{{-- Progress indicator --}}
|
||
|
|
<div class="flex justify-center mt-6 space-x-2">
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">2</div>
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold">3</div>
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold">4</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<form wire:submit="createFeed" class="space-y-6 mt-8 text-left">
|
||
|
|
@if (!empty($errors['general']))
|
||
|
|
<div class="p-3 bg-red-50 border border-red-200 rounded-md">
|
||
|
|
<p class="text-red-600 text-sm">{{ $errors['general'] }}</p>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="feedName" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Feed Name
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
id="feedName"
|
||
|
|
wire:model="feedName"
|
||
|
|
placeholder="My News Feed"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
@error('feedName') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="feedProvider" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
News Provider
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="feedProvider"
|
||
|
|
wire:model="feedProvider"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<option value="">Select news provider</option>
|
||
|
|
@foreach ($feedProviders as $provider)
|
||
|
|
<option value="{{ $provider['code'] }}">{{ $provider['name'] }}</option>
|
||
|
|
@endforeach
|
||
|
|
</select>
|
||
|
|
@error('feedProvider') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="feedLanguageId" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Language
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="feedLanguageId"
|
||
|
|
wire:model="feedLanguageId"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<option value="">Select language</option>
|
||
|
|
@foreach ($languages as $language)
|
||
|
|
<option value="{{ $language->id }}">{{ $language->name }}</option>
|
||
|
|
@endforeach
|
||
|
|
</select>
|
||
|
|
@error('feedLanguageId') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="feedDescription" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Description (Optional)
|
||
|
|
</label>
|
||
|
|
<textarea
|
||
|
|
id="feedDescription"
|
||
|
|
wire:model="feedDescription"
|
||
|
|
rows="3"
|
||
|
|
placeholder="Brief description of this feed"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
></textarea>
|
||
|
|
@error('feedDescription') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="flex justify-between">
|
||
|
|
<button type="button" wire:click="previousStep" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition duration-200">
|
||
|
|
← Back
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
type="submit"
|
||
|
|
@disabled($isLoading)
|
||
|
|
class="bg-blue-600 text-white py-2 px-6 rounded-md hover:bg-blue-700 transition duration-200 disabled:opacity-50"
|
||
|
|
>
|
||
|
|
{{ $isLoading ? 'Creating...' : 'Continue' }}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- Step 4: Channel --}}
|
||
|
|
@if ($step === 4)
|
||
|
|
<div class="text-center mb-8">
|
||
|
|
<h1 class="text-2xl font-bold text-gray-900 mb-2">Configure Your Channel</h1>
|
||
|
|
<p class="text-gray-600">
|
||
|
|
Set up a Lemmy community where articles will be posted
|
||
|
|
</p>
|
||
|
|
|
||
|
|
{{-- Progress indicator --}}
|
||
|
|
<div class="flex justify-center mt-6 space-x-2">
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">3</div>
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold">4</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<form wire:submit="createChannel" class="space-y-6 mt-8 text-left">
|
||
|
|
@if (!empty($errors['general']))
|
||
|
|
<div class="p-3 bg-red-50 border border-red-200 rounded-md">
|
||
|
|
<p class="text-red-600 text-sm">{{ $errors['general'] }}</p>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="channelName" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Community Name
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
id="channelName"
|
||
|
|
wire:model="channelName"
|
||
|
|
placeholder="technology"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<p class="text-sm text-gray-500 mt-1">Enter the community name (without the @ or instance)</p>
|
||
|
|
@error('channelName') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="platformInstanceId" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Platform Instance
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="platformInstanceId"
|
||
|
|
wire:model="platformInstanceId"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<option value="">Select platform instance</option>
|
||
|
|
@foreach ($platformInstances as $instance)
|
||
|
|
<option value="{{ $instance->id }}">{{ $instance->name }} ({{ $instance->url }})</option>
|
||
|
|
@endforeach
|
||
|
|
</select>
|
||
|
|
@error('platformInstanceId') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="channelLanguageId" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Language
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="channelLanguageId"
|
||
|
|
wire:model="channelLanguageId"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<option value="">Select language</option>
|
||
|
|
@foreach ($languages as $language)
|
||
|
|
<option value="{{ $language->id }}">{{ $language->name }}</option>
|
||
|
|
@endforeach
|
||
|
|
</select>
|
||
|
|
@error('channelLanguageId') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="channelDescription" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Description (Optional)
|
||
|
|
</label>
|
||
|
|
<textarea
|
||
|
|
id="channelDescription"
|
||
|
|
wire:model="channelDescription"
|
||
|
|
rows="3"
|
||
|
|
placeholder="Brief description of this channel"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
></textarea>
|
||
|
|
@error('channelDescription') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="flex justify-between">
|
||
|
|
<button type="button" wire:click="previousStep" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition duration-200">
|
||
|
|
← Back
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
type="submit"
|
||
|
|
@disabled($isLoading)
|
||
|
|
class="bg-blue-600 text-white py-2 px-6 rounded-md hover:bg-blue-700 transition duration-200 disabled:opacity-50"
|
||
|
|
>
|
||
|
|
{{ $isLoading ? 'Creating...' : 'Continue' }}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- Step 5: Route --}}
|
||
|
|
@if ($step === 5)
|
||
|
|
<div class="text-center mb-8">
|
||
|
|
<h1 class="text-2xl font-bold text-gray-900 mb-2">Create Your First Route</h1>
|
||
|
|
<p class="text-gray-600">
|
||
|
|
Connect your feed to a channel by creating a route. This tells FFR which articles to post where.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
{{-- Progress indicator --}}
|
||
|
|
<div class="flex justify-center mt-6 space-x-2">
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">4</div>
|
||
|
|
<div class="w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold">5</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<form wire:submit="createRoute" class="space-y-6 mt-8 text-left">
|
||
|
|
@if (!empty($errors['general']))
|
||
|
|
<div class="p-3 bg-red-50 border border-red-200 rounded-md">
|
||
|
|
<p class="text-red-600 text-sm">{{ $errors['general'] }}</p>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="routeFeedId" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Select Feed
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="routeFeedId"
|
||
|
|
wire:model="routeFeedId"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<option value="">Select a feed</option>
|
||
|
|
@foreach ($feeds as $feed)
|
||
|
|
<option value="{{ $feed->id }}">{{ $feed->name }}</option>
|
||
|
|
@endforeach
|
||
|
|
</select>
|
||
|
|
@error('routeFeedId') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="routeChannelId" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Select Channel
|
||
|
|
</label>
|
||
|
|
<select
|
||
|
|
id="routeChannelId"
|
||
|
|
wire:model="routeChannelId"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
required
|
||
|
|
>
|
||
|
|
<option value="">Select a channel</option>
|
||
|
|
@foreach ($channels as $channel)
|
||
|
|
<option value="{{ $channel->id }}">{{ $channel->display_name ?? $channel->name }}</option>
|
||
|
|
@endforeach
|
||
|
|
</select>
|
||
|
|
@if ($channels->isEmpty())
|
||
|
|
<p class="text-sm text-gray-500 mt-1">
|
||
|
|
No channels available. Please create a channel first.
|
||
|
|
</p>
|
||
|
|
@endif
|
||
|
|
@error('routeChannelId') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label for="routePriority" class="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Priority (1-100)
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="number"
|
||
|
|
id="routePriority"
|
||
|
|
wire:model="routePriority"
|
||
|
|
min="1"
|
||
|
|
max="100"
|
||
|
|
placeholder="50"
|
||
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||
|
|
>
|
||
|
|
<p class="text-sm text-gray-500 mt-1">
|
||
|
|
Higher priority routes are processed first (default: 50)
|
||
|
|
</p>
|
||
|
|
@error('routePriority') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="flex justify-between">
|
||
|
|
<button type="button" wire:click="previousStep" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition duration-200">
|
||
|
|
← Back
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
type="submit"
|
||
|
|
@disabled($isLoading || $channels->isEmpty())
|
||
|
|
class="bg-blue-600 text-white py-2 px-6 rounded-md hover:bg-blue-700 transition duration-200 disabled:opacity-50"
|
||
|
|
>
|
||
|
|
{{ $isLoading ? 'Creating...' : 'Continue' }}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- Step 6: Complete --}}
|
||
|
|
@if ($step === 6)
|
||
|
|
<div class="text-center">
|
||
|
|
<div class="mb-6">
|
||
|
|
<div class="w-16 h-16 bg-green-500 text-white rounded-full flex items-center justify-center mx-auto mb-4">
|
||
|
|
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
<h1 class="text-3xl font-bold text-gray-900 mb-2">Setup Complete!</h1>
|
||
|
|
<p class="text-gray-600 mb-6">
|
||
|
|
Great! You've successfully configured FFR. Your feeds will now be monitored and articles will be automatically posted to your configured channels.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{{-- Progress indicator --}}
|
||
|
|
<div class="flex justify-center mb-8 space-x-2">
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
<div class="w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-semibold">✓</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="space-y-4 mb-8">
|
||
|
|
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||
|
|
<h3 class="font-semibold text-blue-900 mb-2">What happens next?</h3>
|
||
|
|
<ul class="text-sm text-blue-800 space-y-1 text-left">
|
||
|
|
<li>• Your feeds will be checked regularly for new articles</li>
|
||
|
|
<li>• New articles will be automatically posted to your channels</li>
|
||
|
|
<li>• You can monitor activity in the Articles and other sections</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
||
|
|
<h3 class="font-semibold text-yellow-900 mb-2">Want more control?</h3>
|
||
|
|
<p class="text-sm text-yellow-800 text-left mb-2">
|
||
|
|
You can add more feeds, channels, and configure settings from the dashboard.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="space-y-3">
|
||
|
|
<button
|
||
|
|
wire:click="completeOnboarding"
|
||
|
|
@disabled($isLoading)
|
||
|
|
class="w-full bg-blue-600 text-white py-3 px-4 rounded-md hover:bg-blue-700 transition duration-200 disabled:opacity-50"
|
||
|
|
>
|
||
|
|
{{ $isLoading ? 'Finishing...' : 'Go to Dashboard' }}
|
||
|
|
</button>
|
||
|
|
|
||
|
|
<div class="text-sm text-gray-500">
|
||
|
|
<a href="{{ route('articles') }}" class="hover:text-blue-600">View Articles</a>
|
||
|
|
•
|
||
|
|
<a href="{{ route('feeds') }}" class="hover:text-blue-600">Manage Feeds</a>
|
||
|
|
•
|
||
|
|
<a href="{{ route('settings') }}" class="hover:text-blue-600">Settings</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
</div>
|
||
|
|
</div>
|