From b1aefa6b3d7817775e62c8c62991e85584a3cba2 Mon Sep 17 00:00:00 2001 From: Dwindi Ramadhana Date: Tue, 3 Feb 2026 22:37:52 +0700 Subject: [PATCH] feat: phase 3 website pages on v1 api --- README.md | 1 + .../Http/Controllers/Web/SiteController.php | 71 ++++++++ app/resources/views/site/api-docs.blade.php | 49 +++++ .../views/site/emoji-detail.blade.php | 53 ++++++ app/resources/views/site/home.blade.php | 169 ++++++++++++++++++ app/resources/views/site/layout.blade.php | 92 ++++++++++ app/resources/views/site/pricing.blade.php | 11 ++ app/resources/views/site/privacy.blade.php | 11 ++ app/resources/views/site/terms.blade.php | 11 ++ app/routes/web.php | 11 +- app/tests/Feature/SitePagesTest.php | 37 ++++ phase-3-website.md | 42 +++++ rebuild-progress.md | 9 +- 13 files changed, 563 insertions(+), 4 deletions(-) create mode 100644 app/app/Http/Controllers/Web/SiteController.php create mode 100644 app/resources/views/site/api-docs.blade.php create mode 100644 app/resources/views/site/emoji-detail.blade.php create mode 100644 app/resources/views/site/home.blade.php create mode 100644 app/resources/views/site/layout.blade.php create mode 100644 app/resources/views/site/pricing.blade.php create mode 100644 app/resources/views/site/privacy.blade.php create mode 100644 app/resources/views/site/terms.blade.php create mode 100644 app/tests/Feature/SitePagesTest.php create mode 100644 phase-3-website.md diff --git a/README.md b/README.md index a22ee00..7a20f83 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ This documentation now uses the corrected legacy/source folders: 4. `rebuild-progress.md` 5. `phase-1-foundation.md` 6. `phase-2-api.md` +7. `phase-3-website.md` ## Note diff --git a/app/app/Http/Controllers/Web/SiteController.php b/app/app/Http/Controllers/Web/SiteController.php new file mode 100644 index 0000000..be75023 --- /dev/null +++ b/app/app/Http/Controllers/Web/SiteController.php @@ -0,0 +1,71 @@ + $match, + ]); + } +} + diff --git a/app/resources/views/site/api-docs.blade.php b/app/resources/views/site/api-docs.blade.php new file mode 100644 index 0000000..50bb6e2 --- /dev/null +++ b/app/resources/views/site/api-docs.blade.php @@ -0,0 +1,49 @@ +@extends('site.layout') + +@section('title', 'API Docs - Dewemoji') + +@section('content') +
+

API Docs

+

Current extension-compatible endpoints exposed by the rebuild app.

+ +

Base URL

+

{{ url('/') }}/v1

+ +

Endpoints

+ + +

Example: emojis

+
GET /v1/emojis?q=love&category=Smileys%20%26%20Emotion&page=1&limit=20
+ +

Example response

+
{
+  "items": [
+    {
+      "emoji": "😀",
+      "name": "grinning face",
+      "slug": "grinning-face",
+      "category": "Smileys & Emotion",
+      "subcategory": "face-smiling",
+      "supports_skin_tone": false,
+      "summary": "A happy smiling face."
+    }
+  ],
+  "total": 1,
+  "page": 1,
+  "limit": 20
+}
+ +

Try it quickly

+

+ Open categories JSON + · + Open emojis JSON +

+
+@endsection + diff --git a/app/resources/views/site/emoji-detail.blade.php b/app/resources/views/site/emoji-detail.blade.php new file mode 100644 index 0000000..9f66c58 --- /dev/null +++ b/app/resources/views/site/emoji-detail.blade.php @@ -0,0 +1,53 @@ +@extends('site.layout') + +@section('title', ($emoji['name'] ?? 'Emoji').' - Dewemoji') + +@section('content') +
+

← Back to emoji list

+ +
+
{{ $emoji['emoji'] ?? '' }}
+
+

{{ $emoji['name'] ?? '' }}

+

{{ $emoji['category'] ?? '' }} / {{ $emoji['subcategory'] ?? '' }}

+

{{ $emoji['description'] ?? '' }}

+
+
+ +
+ +
+ Slug: {{ $emoji['slug'] ?? '' }} + @if(!empty($emoji['unified'])) + Unified: {{ $emoji['unified'] }} + @endif + +
+ + @if(!empty($emoji['keywords_en']) && is_array($emoji['keywords_en'])) +

Keywords (EN)

+
+ @foreach($emoji['keywords_en'] as $kw) + {{ $kw }} + @endforeach +
+ @endif +
+@endsection + +@push('scripts') + +@endpush + diff --git a/app/resources/views/site/home.blade.php b/app/resources/views/site/home.blade.php new file mode 100644 index 0000000..b692135 --- /dev/null +++ b/app/resources/views/site/home.blade.php @@ -0,0 +1,169 @@ +@extends('site.layout') + +@section('title', 'Dewemoji - Emoji Browser') + +@section('content') +
+

Emoji Browser

+

Rebuilt website powered by /v1 APIs.

+ +
+ + + +
+
+ +
+
+ Results + 0 / 0 +
+ +
+ +
+ +
+
+@endsection + +@push('scripts') + +@endpush + diff --git a/app/resources/views/site/layout.blade.php b/app/resources/views/site/layout.blade.php new file mode 100644 index 0000000..5c36151 --- /dev/null +++ b/app/resources/views/site/layout.blade.php @@ -0,0 +1,92 @@ + + + + + + @yield('title', 'Dewemoji') + + @stack('head') + + +
+ +
+ +
+ @yield('content') +
+ + + @stack('scripts') + + + diff --git a/app/resources/views/site/pricing.blade.php b/app/resources/views/site/pricing.blade.php new file mode 100644 index 0000000..fd23950 --- /dev/null +++ b/app/resources/views/site/pricing.blade.php @@ -0,0 +1,11 @@ +@extends('site.layout') + +@section('title', 'Pricing - Dewemoji') + +@section('content') +
+

Pricing

+

Phase 3 placeholder page. We will wire real pricing content and purchase flow in a later phase.

+
+@endsection + diff --git a/app/resources/views/site/privacy.blade.php b/app/resources/views/site/privacy.blade.php new file mode 100644 index 0000000..dbcd82e --- /dev/null +++ b/app/resources/views/site/privacy.blade.php @@ -0,0 +1,11 @@ +@extends('site.layout') + +@section('title', 'Privacy - Dewemoji') + +@section('content') +
+

Privacy

+

Phase 3 placeholder page. We will migrate the full privacy text from legacy content in a later pass.

+
+@endsection + diff --git a/app/resources/views/site/terms.blade.php b/app/resources/views/site/terms.blade.php new file mode 100644 index 0000000..7e18114 --- /dev/null +++ b/app/resources/views/site/terms.blade.php @@ -0,0 +1,11 @@ +@extends('site.layout') + +@section('title', 'Terms - Dewemoji') + +@section('content') +
+

Terms

+

Phase 3 placeholder page. We will migrate complete terms content from legacy sources in a later pass.

+
+@endsection + diff --git a/app/routes/web.php b/app/routes/web.php index 86a06c5..b675c0f 100644 --- a/app/routes/web.php +++ b/app/routes/web.php @@ -1,7 +1,12 @@ name('home'); +Route::get('/api-docs', [SiteController::class, 'apiDocs'])->name('api-docs'); +Route::get('/emoji/{slug}', [SiteController::class, 'emojiDetail'])->name('emoji-detail'); + +Route::get('/pricing', [SiteController::class, 'pricing'])->name('pricing'); +Route::get('/privacy', [SiteController::class, 'privacy'])->name('privacy'); +Route::get('/terms', [SiteController::class, 'terms'])->name('terms'); diff --git a/app/tests/Feature/SitePagesTest.php b/app/tests/Feature/SitePagesTest.php new file mode 100644 index 0000000..9106fc5 --- /dev/null +++ b/app/tests/Feature/SitePagesTest.php @@ -0,0 +1,37 @@ +set('dewemoji.data_path', base_path('tests/Fixtures/emojis.fixture.json')); + } + + public function test_core_pages_are_available(): void + { + $this->get('/')->assertOk(); + $this->get('/api-docs')->assertOk(); + $this->get('/pricing')->assertOk(); + $this->get('/privacy')->assertOk(); + $this->get('/terms')->assertOk(); + } + + public function test_emoji_detail_page_works_with_valid_slug(): void + { + $this->get('/emoji/grinning-face') + ->assertOk() + ->assertSee('grinning face'); + } + + public function test_emoji_detail_page_returns_404_for_unknown_slug(): void + { + $this->get('/emoji/unknown-slug')->assertNotFound(); + } +} + diff --git a/phase-3-website.md b/phase-3-website.md new file mode 100644 index 0000000..61a4d72 --- /dev/null +++ b/phase-3-website.md @@ -0,0 +1,42 @@ +# Phase 3 Website Delivery + +## Implemented routes + +In `app/routes/web.php`: + +- `GET /` (home) +- `GET /emoji/{slug}` (detail) +- `GET /api-docs` +- `GET /pricing` +- `GET /privacy` +- `GET /terms` + +## Implemented pages + +In `app/resources/views/site/`: + +- `layout.blade.php` +- `home.blade.php` +- `emoji-detail.blade.php` +- `api-docs.blade.php` +- `pricing.blade.php` +- `privacy.blade.php` +- `terms.blade.php` + +## Behavior + +- Home page fetches categories and emojis from the new APIs: + - `/v1/categories` + - `/v1/emojis` +- Supports search/category/subcategory filtering and pagination via "Load more". +- Emoji cards link to server-rendered detail page by slug. + +## Controller + +- `app/app/Http/Controllers/Web/SiteController.php` + - Handles page rendering and slug-based emoji lookup from configured dataset. + +## Test coverage + +- `app/tests/Feature/SitePagesTest.php` +- Validates core pages, valid emoji detail, and 404 for invalid slug. diff --git a/rebuild-progress.md b/rebuild-progress.md index 005700c..2135dfa 100644 --- a/rebuild-progress.md +++ b/rebuild-progress.md @@ -34,7 +34,7 @@ - [x] Support both `q` and `query` inputs. ### Phase 3 - Website rebuild -- [ ] Build website pages in new app (index, emoji detail, api docs, legal pages). +- [x] Build website pages in new app (index, emoji detail, api docs, legal pages). - [ ] Replace scaffold in `dewemoji-site` via new NativePHP output. ### Phase 4 - Extension integration @@ -57,3 +57,10 @@ - Routes are now available at `/v1/*` (no `/api` prefix) for extension compatibility. - License verification is currently environment-driven (`DEWEMOJI_LICENSE_ACCEPT_ALL` / `DEWEMOJI_PRO_KEYS`) as a safe stub before real provider integration. - Test coverage added for `v1` endpoints in `app/tests/Feature/ApiV1EndpointsTest.php`. + +## Implementation notes (Phase 3) + +- Added website routes/pages in Laravel app: + - `/`, `/emoji/{slug}`, `/api-docs`, `/pricing`, `/privacy`, `/terms` +- Home page now consumes `/v1/categories` and `/v1/emojis` directly. +- Added page tests in `app/tests/Feature/SitePagesTest.php`.