diff --git a/.codex/CUSTOM_INSTRUCTIONS.md b/.codex/CUSTOM_INSTRUCTIONS.md index 031b84595..639a82667 100644 --- a/.codex/CUSTOM_INSTRUCTIONS.md +++ b/.codex/CUSTOM_INSTRUCTIONS.md @@ -5,3 +5,4 @@ Act as a Senior Laravel & FilamentPHP Architect. Refactor the attached code as a 4. Database: Consolidate migrations into a single file per table or topic (e.g., users, cache, jobs) to reduce the overall number of migration files. 5. Modularity: Use the `laravel-modules` package to encapsulate all features, routing, and Filament resources strictly inside their respective modules. 6. Frontend: Optimize and reduce the CSS footprint while maintaining the exact same visual output. +7. Tooling: Use Laravel Boost as the default framework intelligence layer. Search Laravel Boost documentation before framework-level changes and prefer Boost MCP tools for artisan, browser logs, database inspection, and debugging. diff --git a/.gemini/CUSTOM_INSTRUCTIONS.md b/.gemini/CUSTOM_INSTRUCTIONS.md index a98c16fcd..639a82667 100644 --- a/.gemini/CUSTOM_INSTRUCTIONS.md +++ b/.gemini/CUSTOM_INSTRUCTIONS.md @@ -4,4 +4,5 @@ Act as a Senior Laravel & FilamentPHP Architect. Refactor the attached code as a 3. Refactoring: Move all database logic into Models and extract repetitive Filament code into dedicated Helper classes. Identify and fix any existing logical errors. 4. Database: Consolidate migrations into a single file per table or topic (e.g., users, cache, jobs) to reduce the overall number of migration files. 5. Modularity: Use the `laravel-modules` package to encapsulate all features, routing, and Filament resources strictly inside their respective modules. -6. Frontend: Optimize and reduce the CSS footprint while maintaining the exact same visual output. \ No newline at end of file +6. Frontend: Optimize and reduce the CSS footprint while maintaining the exact same visual output. +7. Tooling: Use Laravel Boost as the default framework intelligence layer. Search Laravel Boost documentation before framework-level changes and prefer Boost MCP tools for artisan, browser logs, database inspection, and debugging. diff --git a/GEMINI.md b/GEMINI.md index 0b86a9f57..c6fb57e2a 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -1,3 +1,14 @@ +Act as a Senior Laravel & FilamentPHP Architect. Refactor the attached code as a greenfield project adhering to the following strict constraints: +1. Architecture: Enforce strict SOLID principles, prioritize brevity, and completely ignore backward compatibility. +2. Cleanup: Remove all legacy code, comments, tests, and PHPDocs. +3. Refactoring: Move all database logic into Models and extract repetitive Filament code into dedicated Helper classes. Identify and fix any existing logical errors. +4. Database: Consolidate migrations into a single file per table or topic (e.g., users, cache, jobs) to reduce the overall number of migration files. +5. Modularity: Use the `laravel-modules` package to encapsulate all features, routing, and Filament resources strictly inside their respective modules. +6. Frontend: Optimize and reduce the CSS footprint while maintaining the exact same visual output. +7. Tooling: Use Laravel Boost as the default framework intelligence layer. Search Laravel Boost documentation before framework-level changes and prefer Boost MCP tools for artisan, browser logs, database inspection, and debugging. + +=== + === foundation rules === diff --git a/Modules/Conversation/resources/assets/js/conversation.js b/Modules/Conversation/resources/assets/js/conversation.js index e54ad5a85..00c36d118 100644 --- a/Modules/Conversation/resources/assets/js/conversation.js +++ b/Modules/Conversation/resources/assets/js/conversation.js @@ -114,10 +114,13 @@ const appendInlineChatMessage = (thread, emptyState, message) => { const initInlineListingChat = () => { const root = document.querySelector('[data-inline-chat]'); - if (!root) { + if (!root || root.dataset.chatBound === '1') { return; } + root.dataset.chatBound = '1'; + + const launcher = root.querySelector('[data-inline-chat-launcher]'); const panel = root.querySelector('[data-inline-chat-panel]'); const thread = root.querySelector('[data-inline-chat-thread]'); const emptyState = root.querySelector('[data-inline-chat-empty]'); @@ -148,9 +151,8 @@ const initInlineListingChat = () => { root.classList.toggle('is-collapsed', state === 'collapsed'); root.classList.toggle('is-sending', state === 'sending'); - if (panel) { - panel.hidden = !isOpen; - } + launcher?.toggleAttribute('hidden', isOpen); + panel?.toggleAttribute('hidden', !isOpen); if (isOpen) { window.requestAnimationFrame(() => { @@ -201,22 +203,47 @@ const initInlineListingChat = () => { updateHeaderInboxBadge(payload?.counts?.unread_messages_total ?? 0); }; - document.querySelectorAll('[data-inline-chat-open]').forEach((button) => { - button.addEventListener('click', async () => { - showError(''); - setState('open'); - await markConversationRead(); - }); + const openChat = async (event) => { + event?.preventDefault(); + event?.stopPropagation(); + + if (root.dataset.state === 'open' || root.dataset.state === 'sending') { + return; + } + + showError(''); + setState('open'); + await markConversationRead(); + }; + + document.querySelectorAll('[data-inline-chat-trigger]').forEach((button) => { + button.addEventListener('click', openChat); }); - root.querySelector('[data-inline-chat-close]')?.addEventListener('click', () => { + launcher?.addEventListener('click', openChat); + + root.querySelector('[data-inline-chat-close]')?.addEventListener('click', (event) => { + event.preventDefault(); + event.stopPropagation(); + if (root.dataset.state === 'collapsed') { + return; + } + + showError(''); setState('collapsed'); }); + root.addEventListener('click', (event) => { + if (event.target.closest('[data-inline-chat-panel]')) { + event.stopPropagation(); + } + }); + form?.addEventListener('submit', async (event) => { event.preventDefault(); + event.stopPropagation(); - if (!input || !submitButton) { + if (!input || !submitButton || root.dataset.state === 'sending') { return; } diff --git a/Modules/Listing/resources/views/themes/otoplus/show.blade.php b/Modules/Listing/resources/views/themes/otoplus/show.blade.php index 446c121a9..e97458d91 100644 --- a/Modules/Listing/resources/views/themes/otoplus/show.blade.php +++ b/Modules/Listing/resources/views/themes/otoplus/show.blade.php @@ -292,7 +292,7 @@ @if(! $listing->user) @elseif($canStartConversation) - + @elseif($isOwnListing) @else @@ -369,7 +369,7 @@ @if(! $listing->user) @elseif($canStartConversation) - + @elseif($isOwnListing) @else @@ -412,7 +412,7 @@ data-read-url="{{ $chatReadUrl }}" data-read-url-template="{{ route('conversations.read', ['conversation' => '__CONVERSATION__']) }}" > -