generated epic 14 with stories to fix the home page also added a pic of the lawyer to the files with a pdf from the client to understand their vision and about them
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
# 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`)
|
||||
Reference in New Issue
Block a user