Working News Section
This commit is contained in:
parent
b57a2a515a
commit
ecd16e5d41
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"laravel-boost": {
|
||||||
|
"command": "/Users/mayoung/Library/Application Support/Herd/bin/php82",
|
||||||
|
"args": [
|
||||||
|
"/Users/mayoung/Herd/meobda-website/artisan",
|
||||||
|
"boost:mcp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"herd": {
|
||||||
|
"command": "/Users/mayoung/Library/Application Support/Herd/bin/php82",
|
||||||
|
"args": [
|
||||||
|
"/Applications/Herd.app/Contents/Resources/herd-mcp.phar"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"SITE_PATH": "/Users/mayoung/Herd/meobda-website"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
enum StoryStatusEnum: string
|
||||||
|
{
|
||||||
|
case DRAFT = 'draft';
|
||||||
|
case SCHEDULED = 'scheduled';
|
||||||
|
case PUBLISHED = 'published';
|
||||||
|
case EXPIRED = 'expired';
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::DRAFT => 'Draft',
|
||||||
|
self::SCHEDULED => 'Scheduled',
|
||||||
|
self::PUBLISHED => 'Published',
|
||||||
|
self::EXPIRED => 'Expired',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function color(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::DRAFT => 'yellow',
|
||||||
|
self::SCHEDULED => 'blue',
|
||||||
|
self::PUBLISHED => 'green',
|
||||||
|
self::EXPIRED => 'red',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\NewsStoryRequest;
|
||||||
use App\Models\NewsStory;
|
use App\Models\NewsStory;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class NewsStoryController extends Controller
|
class NewsStoryController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -14,6 +14,7 @@ class NewsStoryController extends Controller
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$stories = NewsStory::orderBy('id', 'desc')->paginate(15);
|
$stories = NewsStory::orderBy('id', 'desc')->paginate(15);
|
||||||
|
|
||||||
return view('admin.news.index', compact('stories'));
|
return view('admin.news.index', compact('stories'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,33 +29,35 @@ class NewsStoryController extends Controller
|
||||||
/**
|
/**
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(NewsStoryRequest $request)
|
||||||
{
|
{
|
||||||
//
|
NewsStory::create(
|
||||||
|
$request->validated()
|
||||||
|
);
|
||||||
|
|
||||||
|
return redirect()->route('admin.news.index')->with('success', 'Story Added Successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the form for editing the specified resource.
|
* Show the form for editing the specified resource.
|
||||||
*/
|
*/
|
||||||
public function edit(string $id)
|
public function edit(int $newsStoryID)
|
||||||
{
|
{
|
||||||
//
|
$newsStory = NewsStory::findOrFail($newsStoryID);
|
||||||
|
|
||||||
|
return view('admin.news.edit', compact('newsStory'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, string $id)
|
public function update(NewsStoryRequest $request, string $id)
|
||||||
{
|
{
|
||||||
//
|
$newsStory = NewsStory::findOrFail($id);
|
||||||
|
$newsStory->update($request->validated());
|
||||||
|
|
||||||
|
return redirect()->route('admin.news.index')->with('success', 'Story Updated Successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -62,6 +65,9 @@ class NewsStoryController extends Controller
|
||||||
*/
|
*/
|
||||||
public function destroy(string $id)
|
public function destroy(string $id)
|
||||||
{
|
{
|
||||||
//
|
$story = NewsStory::findOrFail($id);
|
||||||
|
$story->delete();
|
||||||
|
|
||||||
|
return redirect()->route('admin.news.index')->with('success', 'Story Deleted Successfully');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\NewsStory;
|
||||||
|
|
||||||
use function siteData;
|
use function siteData;
|
||||||
|
|
||||||
class WelcomeController extends Controller
|
class WelcomeController extends Controller
|
||||||
|
|
@ -17,6 +19,7 @@ class WelcomeController extends Controller
|
||||||
$beginnerClinicDates = siteData('beginnerClinicDates');
|
$beginnerClinicDates = siteData('beginnerClinicDates');
|
||||||
$beginnerClinicLocation = siteData('beginnerClinicLocation');
|
$beginnerClinicLocation = siteData('beginnerClinicLocation');
|
||||||
$officers = siteData('officers');
|
$officers = siteData('officers');
|
||||||
|
$newsStories = NewsStory::published()->orderBy('updated_at', 'desc')->paginate(3);
|
||||||
|
|
||||||
return view('welcome', compact(
|
return view('welcome', compact(
|
||||||
'officers',
|
'officers',
|
||||||
|
|
@ -27,6 +30,7 @@ class WelcomeController extends Controller
|
||||||
'concertClinicDates',
|
'concertClinicDates',
|
||||||
'concertClinicLocation',
|
'concertClinicLocation',
|
||||||
'beginnerClinicDates',
|
'beginnerClinicDates',
|
||||||
'beginnerClinicLocation'));
|
'beginnerClinicLocation',
|
||||||
|
'newsStories'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class NewsStoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'active' => $this->boolean('active'),
|
||||||
|
'scheduleStart' => $this->boolean('scheduleStart'),
|
||||||
|
'scheduleEnd' => $this->boolean('scheduleEnd'),
|
||||||
|
'start_publication_date' => $this->boolean('scheduleStart')
|
||||||
|
? $this->input('start_publication_date')
|
||||||
|
: now()->format('Y-m-d'),
|
||||||
|
'stop_publication_date' => $this->boolean('scheduleEnd')
|
||||||
|
? $this->input('stop_publication_date')
|
||||||
|
: '2100-01-01',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'headline' => ['required', 'string'],
|
||||||
|
'body' => ['required', 'string'],
|
||||||
|
'active' => ['required', 'boolean'],
|
||||||
|
'scheduleStart' => ['sometimes', 'boolean'],
|
||||||
|
'start_publication_date' => ['nullable', 'date'],
|
||||||
|
'scheduleEnd' => ['sometimes', 'boolean'],
|
||||||
|
'stop_publication_date' => ['nullable', 'date', 'after_or_equal:start_publication_date'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,50 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Enums\StoryStatusEnum;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class NewsStory extends Model
|
class NewsStory extends Model
|
||||||
{
|
{
|
||||||
//
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'headline',
|
||||||
|
'body',
|
||||||
|
'active',
|
||||||
|
'start_publication_date',
|
||||||
|
'stop_publication_date',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'active' => 'boolean',
|
||||||
|
'start_publication_date' => 'date',
|
||||||
|
'stop_publication_date' => 'date',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function status(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::make(
|
||||||
|
get: fn () => match (true) {
|
||||||
|
! $this->active => StoryStatusEnum::DRAFT,
|
||||||
|
$this->start_publication_date && now() < $this->start_publication_date => StoryStatusEnum::SCHEDULED,
|
||||||
|
$this->stop_publication_date && now() >= $this->stop_publication_date => StoryStatusEnum::EXPIRED,
|
||||||
|
default => StoryStatusEnum::PUBLISHED,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopePublished($query)
|
||||||
|
{
|
||||||
|
return $query->where('active', true)
|
||||||
|
->where(fn ($q) => $q->whereNull('start_publication_date')
|
||||||
|
->orWhereDate('start_publication_date', '<=', now()))
|
||||||
|
->where(fn ($q) => $q->whereNull('stop_publication_date')
|
||||||
|
->orWhereDate('stop_publication_date', '>=', now()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\NewsStory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
class NewsStoryFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = NewsStory::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'headline' => $this->faker->sentence(),
|
||||||
|
'body' => $this->faker->realText(),
|
||||||
|
'start_publication_date' => Carbon::now(),
|
||||||
|
'stop_publication_date' => Carbon::now()->addDays(7),
|
||||||
|
'active' => '1',
|
||||||
|
'created_at' => Carbon::now(),
|
||||||
|
'updated_at' => Carbon::now(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
<x-layout.admin>
|
<x-layout.admin>
|
||||||
<x-card class="max-w-3xl mx-auto">
|
<x-card class="max-w-3xl mx-auto">
|
||||||
<x-slot:header class="bg-brand-600!">Create News Story</x-slot:header>
|
<x-slot:header class="bg-brand-600!">Create News Story</x-slot:header>
|
||||||
|
|
||||||
<x-slot:body class="bg-white border border-brand-600">
|
<x-slot:body class="bg-white border border-brand-600">
|
||||||
|
@if($errors->any())
|
||||||
|
@foreach($errors->all() as $error)
|
||||||
|
<x-alert color="red">{{ $error }}</x-alert>
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
<x-form method="POST" :action="route('admin.news.store')">
|
<x-form method="POST" :action="route('admin.news.store')">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<x-form.input name="headline" label="Headline"/>
|
<x-form.input name="headline" label="Headline"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
<x-layout.admin>
|
||||||
|
<x-card class="max-w-3xl mx-auto">
|
||||||
|
<x-slot:header class="bg-brand-600!">Create News Story</x-slot:header>
|
||||||
|
|
||||||
|
<x-slot:body class="bg-white border border-brand-600">
|
||||||
|
@if($errors->any())
|
||||||
|
@foreach($errors->all() as $error)
|
||||||
|
<x-alert color="red">{{ $error }}</x-alert>
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
<x-form method="PATCH" :action="route('admin.news.update', $newsStory)">
|
||||||
|
<div>
|
||||||
|
<x-form.input name="headline" label="Headline" value="{{ $newsStory->headline }}" />
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<x-form.textarea name="body" label="Body">
|
||||||
|
{{ $newsStory->body }}
|
||||||
|
</x-form.textarea>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<x-form.radio-group name="active">
|
||||||
|
<x-slot:label>Status</x-slot:label>
|
||||||
|
@if($newsStory->active)
|
||||||
|
<x-form.radio-group-item id="active" value="true" checked>Active</x-form.radio-group-item>
|
||||||
|
<x-form.radio-group-item id="draft" value="false">Draft</x-form.radio-group-item>
|
||||||
|
@else
|
||||||
|
<x-form.radio-group-item id="active" value="true">Active</x-form.radio-group-item>
|
||||||
|
<x-form.radio-group-item id="draft" value="false" checked>Draft</x-form.radio-group-item>
|
||||||
|
@endif
|
||||||
|
</x-form.radio-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div x-data="{ showStartDate: {{ $newsStory->start_publication_date ? 'true' : 'false' }} }" class="mt-3">
|
||||||
|
<x-form.checkbox name="scheduleStart" x-model="showStartDate" value="true"
|
||||||
|
label="Schedule Publication"/>
|
||||||
|
<x-form.input
|
||||||
|
type="date"
|
||||||
|
name="start_publication_date"
|
||||||
|
label=""
|
||||||
|
value="{{ $newsStory->start_publication_date?->toDateString() ?? now()->toDateString() }}"
|
||||||
|
x-show="showStartDate"
|
||||||
|
x-cloak
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div x-data="{ showEndDate: {{ $newsStory->stop_publication_date ? 'true' : 'false' }} }" class="mt-3">
|
||||||
|
<x-form.checkbox name="scheduleEnd" x-model="showEndDate" value="true" label="Schedule Removal"/>
|
||||||
|
<x-form.input
|
||||||
|
type="date"
|
||||||
|
name="stop_publication_date"
|
||||||
|
label=""
|
||||||
|
value="{{ $newsStory->stop_publication_date?->toDateString() ?? '' }}"
|
||||||
|
x-show="showEndDate"
|
||||||
|
x-cloak
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-right">
|
||||||
|
<x-form.button type="submit">Save Story</x-form.button>
|
||||||
|
</div>
|
||||||
|
</x-form>
|
||||||
|
</x-slot:body>
|
||||||
|
</x-card>
|
||||||
|
</x-layout.admin>
|
||||||
|
|
@ -1,10 +1,47 @@
|
||||||
<x-layout.admin>
|
<x-layout.admin>
|
||||||
<x-card class="max-w-3xl mx-auto">
|
<x-card class="">
|
||||||
<x-slot:header class="bg-brand-600!">News Stories</x-slot:header>
|
<x-slot:header class="bg-brand-600!">News Stories</x-slot:header>
|
||||||
<x-slot:body class="bg-white border border-brand-600">
|
<x-slot:body class="bg-white border border-brand-600">
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<x-form.button type="link" :href="route('admin.news.create')">New Story</x-form.button>
|
<x-form.button type="link" :href="route('admin.news.create')">New Story</x-form.button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<x-table>
|
||||||
|
<x-slot:header>
|
||||||
|
<x-table.th></x-table.th>
|
||||||
|
<x-table.th>Headline</x-table.th>
|
||||||
|
<x-table.th>Status</x-table.th>
|
||||||
|
<x-table.th>Submission Date</x-table.th>
|
||||||
|
<x-table.th>Start Publication</x-table.th>
|
||||||
|
<x-table.th>Stop Publication</x-table.th>
|
||||||
|
</x-slot:header>
|
||||||
|
@foreach($stories as $story)
|
||||||
|
<tr>
|
||||||
|
<x-table.td class="flex gap-3 ">
|
||||||
|
<a href="{{route('admin.news.edit', $story)}}">
|
||||||
|
<x-heroicon-s-pencil-square class="size-5"/>
|
||||||
|
</a>
|
||||||
|
<x-modal-danger id="delete-{{$story->id}}" form-method="DELETE" form-action="{{ route('admin.news.destroy', $story) }}">
|
||||||
|
<x-slot:heading>Confirm Story Deletion</x-slot:heading>
|
||||||
|
<x-slot:affirmativeButton type="submit">Delete</x-slot:affirmativeButton>
|
||||||
|
<x-slot:openButton><x-heroicon-s-trash class="size-5" /></x-slot:openButton>
|
||||||
|
Do you really want to delete the story with the headline<br />{{ $story->headline }}?
|
||||||
|
</x-modal-danger>
|
||||||
|
</x-table.td>
|
||||||
|
<x-table.td>{{ $story->headline }}</x-table.td>
|
||||||
|
<x-table.td>
|
||||||
|
<x-badge-pill :color="$story->status->color()">
|
||||||
|
{{ $story->status->label() }}
|
||||||
|
</x-badge-pill>
|
||||||
|
</x-table.td>
|
||||||
|
<x-table.td>{{ $story->created_at->format('m/d/Y') }}</x-table.td>
|
||||||
|
<x-table.td>{{ $story->start_publication_date->format('m/d/Y') }}</x-table.td>
|
||||||
|
<x-table.td>{{ $story->stop_publication_date?->format('m/d/Y') }}</x-table.td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table>
|
||||||
|
</div>
|
||||||
</x-slot:body>
|
</x-slot:body>
|
||||||
</x-card>
|
</x-card>
|
||||||
</x-layout.admin>
|
</x-layout.admin>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
@props(['color' => 'blue'])
|
@props(['color' => 'blue'])
|
||||||
<div class="border-l-4 ">
|
<div @class([
|
||||||
<div @class([
|
'border-l-4 p-2 mb-3 ',
|
||||||
'border-l-4 p4 ',
|
|
||||||
'border-yellow-400 bg-yellow-50 dark:border-yellow-500 dark:bg-yellow-500/10' => $color === 'yellow',
|
'border-yellow-400 bg-yellow-50 dark:border-yellow-500 dark:bg-yellow-500/10' => $color === 'yellow',
|
||||||
'border-red-400 bg-red-50 dark:border-red-500 dark:bg-red-500/15' => $color === 'red',
|
'border-red-400 bg-red-50 dark:border-red-500 dark:bg-red-500/15' => $color === 'red',
|
||||||
'border-green-400 bg-green-50 dark:border-green-500 dark:bg-green-500/10' => $color === 'green',
|
'border-green-400 bg-green-50 dark:border-green-500 dark:bg-green-500/10' => $color === 'green',
|
||||||
|
|
@ -31,8 +30,8 @@
|
||||||
'text-red-700 dar:text-red-300' => $color === 'red',
|
'text-red-700 dar:text-red-300' => $color === 'red',
|
||||||
'text-green-700 dar:text-green-300' => $color === 'green',
|
'text-green-700 dar:text-green-300' => $color === 'green',
|
||||||
])>
|
])>
|
||||||
You have no credits left.
|
{{ $slot }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
@props(['color' => 'blue'])
|
||||||
|
|
||||||
|
<span @class([
|
||||||
|
'inline-flex items-center rounded-full px-2 py-1 text-xs font-medium',
|
||||||
|
'bg-red-50 text-red-700 inset-ring inset-ring-red-600/10 dark:bg-red-400/10 dark:text-red-400 dark:inset-ring-red-400/20' => $color === 'red',
|
||||||
|
'bg-gray-50 text-gray-600 inset-ring inset-ring-gray-500/10 dark:bg-gray-400/10 dark:text-gray-400 dark:inset-ring-gray-400/20' => $color === 'gray',
|
||||||
|
'bg-yellow-50 text-yellow-800 inset-ring inset-ring-yellow-600/20 dark:bg-yellow-400/10 dark:text-yellow-500 dark:inset-ring-yellow-400/20' => $color === 'yellow',
|
||||||
|
'bg-green-50 text-green-700 inset-ring inset-ring-green-600/20 dark:bg-green-400/10 dark:text-green-400 dark:inset-ring-green-500/20' => $color === 'green',
|
||||||
|
'bg-blue-50 text-blue-700 inset-ring inset-ring-blue-700/10 dark:bg-blue-400/10 dark:text-blue-400 dark:inset-ring-blue-400/30' => $color === 'blue',
|
||||||
|
'bg-indigo-50 text-indigo-700 inset-ring inset-ring-indigo-700/10 dark:bg-indigo-400/10 dark:text-indigo-400 dark:inset-ring-indigo-400/30' => $color === 'indigo',
|
||||||
|
'bg-purple-50 text-purple-700 inset-ring inset-ring-purple-700/10 dark:bg-purple-400/10 dark:text-purple-400 dark:inset-ring-purple-400/30' => $color === 'purple',
|
||||||
|
'bg-pink-50 text-pink-700 inset-ring inset-ring-pink-700/10 dark:bg-pink-400/10 dark:text-pink-400 dark:inset-ring-pink-400/20' => $color === 'pink',
|
||||||
|
])>
|
||||||
|
{{ $slot }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
@props(['id', 'openButton', 'heading', 'affirmativeButton', 'formMethod', 'formAction'])
|
||||||
|
<button command="show-modal" commandfor="{{ $id }}"
|
||||||
|
class="rounded-md bg-gray-950/5 px-2.5 py-1.5 text-sm font-semibold text-gray-900 hover:bg-gray-950/10 dark:bg-white/10 dark:text-white dark:inset-ring dark:inset-ring-white/5 dark:hover:bg-white/20">
|
||||||
|
{{ $openButton }}
|
||||||
|
</button>
|
||||||
|
<el-dialog>
|
||||||
|
<dialog id="{{ $id }}" aria-labelledby="dialog-title"
|
||||||
|
class="fixed inset-0 size-auto max-h-none max-w-none overflow-y-auto bg-transparent backdrop:bg-transparent">
|
||||||
|
<el-dialog-backdrop
|
||||||
|
class="fixed inset-0 bg-gray-500/75 transition-opacity data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in dark:bg-gray-900/50"></el-dialog-backdrop>
|
||||||
|
|
||||||
|
<div tabindex="0"
|
||||||
|
class="flex min-h-full items-end justify-center p-4 text-center focus:outline-none sm:items-center sm:p-0">
|
||||||
|
<el-dialog-panel
|
||||||
|
class="relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all data-closed:translate-y-4 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in sm:my-8 sm:w-full sm:max-w-lg sm:p-6 data-closed:sm:translate-y-0 data-closed:sm:scale-95 dark:bg-gray-800 dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
|
<x-form method="{{$formMethod}}" action="{{$formAction}}">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex size-12 shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:size-10 dark:bg-red-500/10">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"
|
||||||
|
data-slot="icon" aria-hidden="true" class="size-6 text-red-600 dark:text-red-400">
|
||||||
|
<path
|
||||||
|
d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 id="dialog-title"
|
||||||
|
class="text-base font-semibold text-gray-900 dark:text-white">{{ $heading }}</h3>
|
||||||
|
<div class="mt-2">
|
||||||
|
<p {{ $attributes->merge(['class'=>'text-sm text-gray-500 dark:text-gray-400']) }}>{{ $slot }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
|
||||||
|
<button type="submit"
|
||||||
|
class="inline-flex w-full justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-red-500 sm:ml-3 sm:w-auto dark:bg-red-500 dark:shadow-none dark:hover:bg-red-400">
|
||||||
|
{{ $affirmativeButton }}
|
||||||
|
</button>
|
||||||
|
<button type="button" command="close" commandfor="{{ $id }}"
|
||||||
|
class="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-xs inset-ring-1 inset-ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto dark:bg-white/10 dark:text-white dark:shadow-none dark:inset-ring-white/5 dark:hover:bg-white/20">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</x-form>
|
||||||
|
</el-dialog-panel>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
</el-dialog>
|
||||||
|
|
@ -52,9 +52,26 @@
|
||||||
</x-card>
|
</x-card>
|
||||||
|
|
||||||
<div class="sm:col-span-2 lg:col-start-2 mt-5">
|
<div class="sm:col-span-2 lg:col-start-2 mt-5">
|
||||||
<x-card>
|
@foreach($newsStories as $story)
|
||||||
<x-slot:header>News Story</x-slot:header>
|
<x-card class="mb-5 ">
|
||||||
|
<x-slot:header>{{ $story->headline }}</x-slot:header>
|
||||||
|
|
||||||
|
<p class="text-xs italic">
|
||||||
|
Published: {{ $story->start_publication_date->format('m/d/Y') ?? $story->created_at->format('m/d/Y') }}</p>
|
||||||
|
@if($story->created_at->format('m/d/Y') != $story->updated_at->format('m/d/Y'))
|
||||||
|
<p class="mt-1 text-xs italic">Last Updated: {{ $story->updated_at->format('m/d/Y') }}</p>
|
||||||
|
@endif
|
||||||
|
<div class="mt-3">
|
||||||
|
{{ $story->body }}
|
||||||
|
</div>
|
||||||
</x-card>
|
</x-card>
|
||||||
|
@endforeach
|
||||||
|
@if($newsStories->hasPages())
|
||||||
|
<x-card>
|
||||||
|
<x-slot:header>See More Stories</x-slot:header>
|
||||||
|
{{ $newsStories->links() }}
|
||||||
|
</x-card>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -26,5 +26,5 @@ Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function ()
|
||||||
Route::get('/', [UsersController::class, 'index'])->name('index');
|
Route::get('/', [UsersController::class, 'index'])->name('index');
|
||||||
});
|
});
|
||||||
Route::resource('/etudes', AuditionEtudeController::class)->names('etudes');
|
Route::resource('/etudes', AuditionEtudeController::class)->names('etudes');
|
||||||
Route::resource('/news', NewsStoryController::class)->names('news');
|
Route::resource('/news', NewsStoryController::class)->except(['show'])->names('news');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue