takeone-youtube-clone/.claude/component-usage.md
ghassan 0b2e95ea65 Add NAS file manager integration and all pending platform changes
- Installed p7h/nas-file-manager package via private VCS repo
- Published config/nas-file-manager.php with super_admin middleware restriction
- Added NAS env vars to .env.example
- Created admin/nas-storage page with connection info panel and file browser widget
- Added NAS Storage link to admin sidebar (super_admin only)
- Added SuperAdminController@nasStorage method and admin.nas-storage route
- Includes all accumulated branch changes: profile wall, 2FA, audit logs,
  settings panel, country/phone/timezone components, posts, slideshow,
  playlist shares, video downloads/shares, comment likes, notifications,
  social links, and more

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 13:24:32 +03:00

187 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Reusable Select Component Usage
This file tracks every page/partial that uses `<x-phone-code-select>`, `<x-country-select>`, or `<x-timezone-select>`.
**Update this file whenever you add or remove a component from a view.**
When modifying any component or its data source (`app/Data/Countries.php`), check all pages in the relevant section below and verify the change works correctly in each context.
---
## Data source
**`app/Data/Countries.php`** — `App\Data\Countries`
| Method | Used by component |
|---|---|
| `Countries::forPhoneCode()` | `<x-phone-code-select>` |
| `Countries::forCountry()` | `<x-country-select>` |
| `Countries::forTimezone()` | `<x-timezone-select>` |
| `Countries::all()` | All three (via the above methods) |
Adding or renaming a field in `Countries::all()` requires updating the corresponding `for*()` method too.
---
## Shared CSS / JS
The `.csd-*` CSS rules and the `window.CSD` class are duplicated across all three component files inside `@once` guards. If you change the look or behaviour of the dropdown, **update all three component files**:
- `resources/views/components/phone-code-select.blade.php`
- `resources/views/components/country-select.blade.php`
- `resources/views/components/timezone-select.blade.php`
The `@once` Blade directive ensures the browser only receives one copy of the CSS/JS even when multiple components are on the same page.
---
## `<x-video-insights>`
**File:** `resources/views/components/video-insights.blade.php`
**Props:** `:video``Video` model instance.
**Behaviour:** Renders the Insights tab panel (`<div class="vdb-panel" id="vdb-insights">`), the drill-down modal, all `.ins-*` CSS, and all insights JS (`loadInsights`, `renderInsights`, modal openers, country/day/downloader drill-downs). Only renders if `Auth::id() === $video->user_id`. Must be placed **inside `.vdb-wrap`**, after the About panel, so the tab-switch CSS applies. The parent view must call `loadInsights()` (global, defined by this component) when the Insights tab is activated.
**Data source:** `GET /videos/{video}/insights` (JSON) + drill-down routes `/insights/country/{code}`, `/insights/day/{date}`, `/insights/downloader/{userId}`.
| View file | Placement | Notes |
|---|---|---|
| `resources/views/videos/partials/description-box.blade.php` | Inside `.vdb-wrap`, after About panel | Used by all three video type views (generic, match, music) |
| `resources/views/videos/show.blade.php` | Inside `.vdb-wrap`, after About panel | Legacy view (not rendered by controller — kept in sync) |
---
## `<x-social-links-editor>`
**File:** `resources/views/components/social-links-editor.blade.php`
**Props:** `existing` — associative array keyed by platform name (e.g. `['twitter' => 'handle', 'whatsapp' => '97312345678']`).
**Behaviour:** Dynamic add/remove rows; each row has a custom icon dropdown to pick the platform and a text input for the value. Supported platforms: `twitter`, `instagram`, `facebook`, `youtube`, `linkedin`, `tiktok`, `whatsapp`, `website`, `google_location`, `social_phone`, `social_email`. Hidden clear inputs ensure removed entries are cleared on save. Must be placed **inside a `<form>`**.
**DB columns:** `twitter`, `instagram`, `facebook`, `youtube`, `linkedin`, `tiktok`, `website` (legacy), `whatsapp`, `google_location`, `social_phone`, `social_email`.
| View file | Placement | Notes |
|---|---|---|
| `resources/views/user/profile.blade.php` | Social tab of Edit Profile modal | `$socialExisting` array passed from `@php` block above `@section('scripts')` |
---
## `<x-date-picker>`
**File:** `resources/views/components/date-picker.blade.php`
**Stored value:** `YYYY-MM-DD` string in a hidden input (same format as `<input type="date">`).
**Props:** `name`, `id`, `value`, `label`, `required`, `class`, `style`, `minYear` (default 1900), `maxYear` (default current year).
**Behaviour:** Day grid (5 columns, 131), month list (JanuaryDecember), year searchable list (descending). Days auto-constrain on month/year change; invalid selected day resets automatically.
| View file | Field name | Notes |
|---|---|---|
| `resources/views/user/profile.blade.php` | `birthday` | Replaces `<input type="date">` |
| `resources/views/auth/register.blade.php` | `birthday` | Registration form — mandatory |
---
## `<x-image-cropper>`
**File:** `resources/views/components/image-cropper.blade.php`
**Props:** `id` (unique, required), `width` (px, default 300), `height` (px, default 300), `shape` (`circle`|`square`, default `circle`), `folder` (storage subfolder), `filename` (base name without extension), `callback` (JS function name called with URL on success), `update-url` (endpoint to POST `{path}` after crop to update DB), `title` (modal heading).
**Behaviour:** Renders a full-screen dark-themed modal with Cropme.js. Shows camera icon on avatar/banner hover (owner only). After crop: POSTs base64 to `/image-upload`, optionally POSTs the path to `update-url`, then calls `callback(url)`. Uses local assets (`public/js/cropme.min.js`, `public/css/cropme.min.css`). No jQuery required.
**Assets needed:** `public/js/cropme.min.js`, `public/css/cropme.min.css`.
**Routes needed:** `image.upload` (POST `/image-upload`).
| View file | id / use | Notes |
|---|---|---|
| `resources/views/user/channel.blade.php` | `avatar` — circle 300×300 | Owner only; `update-url = profile.updateAvatar`; callback `onAvatarSaved` |
| `resources/views/user/channel.blade.php` | `banner` — square 500×160 | Owner only; `update-url = profile.updateBanner`; callback `onBannerSaved` |
| `resources/views/layouts/partials/upload-modal.blade.php` | `thumb_upload` — square 448×252 | Form mode; `target-input=thumbnail-modal`; output 1280px |
| `resources/views/layouts/partials/edit-video-modal.blade.php` | `thumb_edit` — square 448×252 | Form mode; `target-input=edit-thumbnail-input`; output 1280px |
| `resources/views/videos/create.blade.php` | `thumb_create_mobile` — square 448×252 | Mobile; `target-input=thumbnail`; output 1280px |
| `resources/views/videos/edit.blade.php` | `thumb_edit_mobile` — square 448×252 | Mobile; `target-input=edit-thumbnail`; output 1280px |
| `resources/views/playlists/index.blade.php` | `thumb_pl_create` — square 448×252 | Form mode; `target-input=playlist-thumbnail-input`; output 1280px |
| `resources/views/playlists/show.blade.php` | `thumb_pl_edit` — square 448×252 | Form mode; `target-input=playlistThumbnailInput`; output 1280px |
---
## `<x-gender-select>`
**File:** `resources/views/components/gender-select.blade.php`
**Props:** `name`, `id`, `value` (ISO string: `"male"` or `"female"`), `label`, `required`, `class`, `style`.
**Behaviour:** Custom dropdown with blue ♂ (male) and pink ♀ (female) symbols. No search needed. Stores value as `"male"` or `"female"`.
| View file | Field name | Notes |
|---|---|---|
| `resources/views/auth/register.blade.php` | `gender` | Registration form — mandatory |
---
## `<x-phone-code-select>`
Stored value format: `"+973|BH"` (dial_code + pipe + ISO2).
To read only the dial code from a stored value: `explode('|', $value)[0]`.
| View file | Field name | Notes |
|---|---|---|
| `resources/views/user/profile.blade.php` | `phone_code` | Paired with `phone_number` text input |
---
## `<x-country-select>`
Stored value: ISO2 code (e.g. `"BH"`).
| View file | Field name | Notes |
|---|---|---|
| `resources/views/user/profile.blade.php` | `nationality` | Edit Profile form |
| `resources/views/auth/register.blade.php` | `nationality` | Registration form — mandatory |
---
## `<x-timezone-select>`
Stored value: IANA timezone string (e.g. `"Asia/Bahrain"`).
| View file | Field name | Notes |
|---|---|---|
| `resources/views/user/profile.blade.php` | `timezone` | Edit Profile form |
---
## Usage example
```blade
{{-- Phone code + number side by side --}}
<div style="display:flex; gap:8px;">
<x-phone-code-select
name="phone_code"
value="+973|BH"
label="Phone"
required
style="width:140px; flex-shrink:0;"
/>
<input type="tel" name="phone_number" class="form-control">
</div>
{{-- Country / nationality --}}
<x-country-select
name="nationality"
label="Nationality"
placeholder="Select nationality"
value="{{ old('nationality', $user->nationality) }}"
required
/>
{{-- Timezone --}}
<x-timezone-select
name="timezone"
label="Timezone"
value="{{ old('timezone', $user->timezone ?? 'Asia/Bahrain') }}"
required
/>
```
---
## Modification checklist
When you modify any of these components, work through this list:
- [ ] Update `app/Data/Countries.php` if the data structure changes
- [ ] Update all three `.blade.php` component files if shared CSS/JS changes
- [ ] Update the `for*()` method in `Countries.php` that feeds the changed component
- [ ] Re-test every page listed in the usage tables above
- [ ] Add/remove rows from the usage tables if views were added or removed