247 lines
6.7 KiB
Markdown
247 lines
6.7 KiB
Markdown
# Story 14.5: Latest Posts Section
|
|
|
|
## Story
|
|
|
|
**As a** website visitor
|
|
**I want to** see recent legal articles and updates on the home page
|
|
**So that** I can access valuable legal content and see that the firm is active
|
|
|
|
## Acceptance Criteria
|
|
|
|
### AC1: Section Container
|
|
|
|
**Given** a visitor scrolls to the latest posts section
|
|
**When** viewing the section
|
|
**Then** display with:
|
|
- Warm Cream (`#F4F1EA`) background
|
|
- Section ID `id="posts"` for anchor linking
|
|
- Adequate padding (64px vertical on desktop)
|
|
|
|
### AC2: Section Heading
|
|
|
|
**Given** the latest posts section
|
|
**When** displayed
|
|
**Then** show a section heading:
|
|
- English: "Latest Articles" or "Legal Insights"
|
|
- Arabic: "أحدث المقالات" or "رؤى قانونية"
|
|
- Typography: H2, SemiBold, Forest Green (`#2D322A`)
|
|
- Centered alignment
|
|
|
|
### AC3: Display 3 Latest Posts
|
|
|
|
**Given** the posts section
|
|
**When** posts exist in the database
|
|
**Then** display the 3 most recent published posts showing:
|
|
- Post title
|
|
- Publication date
|
|
- Brief excerpt (first 100-150 characters of body)
|
|
- "Read More" link
|
|
|
|
### AC4: Post Card Design
|
|
|
|
**Given** each post card
|
|
**When** displayed
|
|
**Then** include:
|
|
- Card background: White (`#FFFFFF`)
|
|
- Title: Bold, Forest Green (`#2D322A`), clickable link
|
|
- Date: Small text, muted color
|
|
- Excerpt: Body text, truncated with ellipsis
|
|
- "Read More" link: Warm Gold (`#A68966`)
|
|
- Subtle shadow and border-radius
|
|
- Hover effect on card or title
|
|
|
|
### AC5: Empty State
|
|
|
|
**Given** the posts section
|
|
**When** no published posts exist
|
|
**Then** either:
|
|
- Hide the entire section, OR
|
|
- Show a message: "Articles coming soon" / "المقالات قريباً"
|
|
|
|
### AC6: View All Link
|
|
|
|
**Given** the posts section
|
|
**When** posts are displayed
|
|
**Then** show a "View All Articles" / "عرض جميع المقالات" link:
|
|
- Links to `/posts`
|
|
- Styled as secondary button or text link with arrow
|
|
- Positioned below the post cards, centered
|
|
|
|
### AC7: Grid Layout
|
|
|
|
**Given** different screen sizes
|
|
**When** viewing the posts section:
|
|
- **Desktop (≥992px):** 3 columns (1 row of 3 cards)
|
|
- **Tablet (576-991px):** 2 columns + 1 below, or 3 columns
|
|
- **Mobile (<576px):** 1 column (3 rows, stacked)
|
|
|
|
### AC8: RTL Support
|
|
|
|
**Given** Arabic language is selected
|
|
**When** viewing the posts section
|
|
**Then** cards and text align right-to-left correctly
|
|
|
|
### AC9: Dynamic Data
|
|
|
|
**Given** the posts section
|
|
**When** rendered
|
|
**Then** query posts from database:
|
|
```php
|
|
Post::where('status', 'published')
|
|
->latest()
|
|
->take(3)
|
|
->get()
|
|
```
|
|
|
|
## Technical Notes
|
|
|
|
### Files to Modify
|
|
- `resources/views/pages/home.blade.php` - Add posts section with data query
|
|
- `lang/en/home.php` - Add translations
|
|
- `lang/ar/home.php` - Add translations
|
|
|
|
### Controller/Page Component
|
|
|
|
The home page needs to pass posts data. Options:
|
|
1. Use a Livewire/Volt component to fetch posts
|
|
2. Pass posts via route closure or controller
|
|
|
|
**Option 1: Volt Component (Recommended)**
|
|
|
|
Convert `home.blade.php` to a Volt component:
|
|
|
|
```php
|
|
<?php
|
|
use App\Models\Post;
|
|
use Livewire\Volt\Component;
|
|
|
|
new class extends Component {
|
|
public function with(): array
|
|
{
|
|
return [
|
|
'latestPosts' => Post::where('status', 'published')
|
|
->latest()
|
|
->take(3)
|
|
->get(),
|
|
];
|
|
}
|
|
}; ?>
|
|
```
|
|
|
|
**Option 2: Route with data**
|
|
|
|
```php
|
|
// routes/web.php
|
|
Route::get('/', function () {
|
|
return view('pages.home', [
|
|
'latestPosts' => Post::where('status', 'published')
|
|
->latest()
|
|
->take(3)
|
|
->get(),
|
|
]);
|
|
})->name('home');
|
|
```
|
|
|
|
### HTML Structure
|
|
|
|
```blade
|
|
@if($latestPosts->count() > 0)
|
|
<section id="posts" class="py-16 lg:py-20 bg-background">
|
|
<div class="container mx-auto px-4">
|
|
<div class="text-center mb-12">
|
|
<h2 class="text-2xl lg:text-3xl font-semibold text-text mb-4">
|
|
{{ __('home.posts_title') }}
|
|
</h2>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
|
@foreach($latestPosts as $post)
|
|
<article class="bg-card p-6 rounded-lg shadow-card">
|
|
<time class="text-xs text-body/70 mb-2 block">
|
|
{{ $post->created_at->translatedFormat('j F Y') }}
|
|
</time>
|
|
<h3 class="text-lg font-bold text-text mb-3">
|
|
<a href="{{ route('posts.show', $post) }}" class="hover:text-cta transition-colors">
|
|
{{ $post->title }}
|
|
</a>
|
|
</h3>
|
|
<p class="text-body text-sm mb-4 line-clamp-3">
|
|
{{ Str::limit(strip_tags($post->body), 150) }}
|
|
</p>
|
|
<a href="{{ route('posts.show', $post) }}" class="text-cta font-medium text-sm hover:text-cta-hover">
|
|
{{ __('home.read_more') }} →
|
|
</a>
|
|
</article>
|
|
@endforeach
|
|
</div>
|
|
|
|
<div class="text-center">
|
|
<flux:button variant="ghost" href="{{ route('posts.index') }}">
|
|
{{ __('home.view_all_posts') }}
|
|
</flux:button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
@endif
|
|
```
|
|
|
|
### Translation Keys
|
|
|
|
```php
|
|
// lang/en/home.php (additions)
|
|
'posts_title' => 'Latest Articles',
|
|
'read_more' => 'Read More',
|
|
'view_all_posts' => 'View All Articles',
|
|
'posts_empty' => 'Articles coming soon',
|
|
|
|
// lang/ar/home.php (additions)
|
|
'posts_title' => 'أحدث المقالات',
|
|
'read_more' => 'اقرأ المزيد',
|
|
'view_all_posts' => 'عرض جميع المقالات',
|
|
'posts_empty' => 'المقالات قريباً',
|
|
```
|
|
|
|
### Post Model Reference
|
|
|
|
Existing Post model fields:
|
|
- `title` - Post title (bilingual stored via JSON or separate fields)
|
|
- `body` - Post content
|
|
- `status` - 'draft' or 'published'
|
|
- `created_at` - Timestamp
|
|
|
|
### Date Formatting
|
|
|
|
Use Laravel's `translatedFormat()` for bilingual dates:
|
|
```php
|
|
$post->created_at->translatedFormat('j F Y')
|
|
// English: "15 January 2026"
|
|
// Arabic: "15 يناير 2026"
|
|
```
|
|
|
|
## Dev Checklist
|
|
|
|
- [ ] Determine data passing method (Volt component or route)
|
|
- [ ] Create posts section HTML structure
|
|
- [ ] Add section heading with translations
|
|
- [ ] Implement post card design
|
|
- [ ] Query and display 3 latest published posts
|
|
- [ ] Add date formatting with translation support
|
|
- [ ] Implement excerpt truncation
|
|
- [ ] Add "Read More" links to individual posts
|
|
- [ ] Add "View All" link to posts index
|
|
- [ ] Handle empty state (hide section or show message)
|
|
- [ ] Implement responsive grid layout
|
|
- [ ] Test RTL layout
|
|
- [ ] Verify links work correctly
|
|
|
|
## Estimation
|
|
|
|
**Complexity:** Medium (requires data fetching)
|
|
**Risk:** Low - Uses existing Post model and routes
|
|
|
|
## Dependencies
|
|
|
|
- Previous stories for page structure
|
|
- Existing Post model
|
|
- Posts routes (`posts.index`, `posts.show`)
|