mirror of
https://github.com/openclassify/openclassify.git
synced 2026-04-14 11:12:09 -05:00
Fix modal chat toggling issue
This commit is contained in:
parent
4e0ed5ca36
commit
4f0b6d0ef2
@ -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.
|
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.
|
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.
|
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.
|
||||||
|
|||||||
@ -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.
|
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.
|
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.
|
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.
|
||||||
|
|||||||
11
GEMINI.md
11
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.
|
||||||
|
|
||||||
|
===
|
||||||
|
|
||||||
<laravel-boost-guidelines>
|
<laravel-boost-guidelines>
|
||||||
=== foundation rules ===
|
=== foundation rules ===
|
||||||
|
|
||||||
|
|||||||
@ -114,10 +114,13 @@ const appendInlineChatMessage = (thread, emptyState, message) => {
|
|||||||
const initInlineListingChat = () => {
|
const initInlineListingChat = () => {
|
||||||
const root = document.querySelector('[data-inline-chat]');
|
const root = document.querySelector('[data-inline-chat]');
|
||||||
|
|
||||||
if (!root) {
|
if (!root || root.dataset.chatBound === '1') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root.dataset.chatBound = '1';
|
||||||
|
|
||||||
|
const launcher = root.querySelector('[data-inline-chat-launcher]');
|
||||||
const panel = root.querySelector('[data-inline-chat-panel]');
|
const panel = root.querySelector('[data-inline-chat-panel]');
|
||||||
const thread = root.querySelector('[data-inline-chat-thread]');
|
const thread = root.querySelector('[data-inline-chat-thread]');
|
||||||
const emptyState = root.querySelector('[data-inline-chat-empty]');
|
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-collapsed', state === 'collapsed');
|
||||||
root.classList.toggle('is-sending', state === 'sending');
|
root.classList.toggle('is-sending', state === 'sending');
|
||||||
|
|
||||||
if (panel) {
|
launcher?.toggleAttribute('hidden', isOpen);
|
||||||
panel.hidden = !isOpen;
|
panel?.toggleAttribute('hidden', !isOpen);
|
||||||
}
|
|
||||||
|
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
@ -201,22 +203,47 @@ const initInlineListingChat = () => {
|
|||||||
updateHeaderInboxBadge(payload?.counts?.unread_messages_total ?? 0);
|
updateHeaderInboxBadge(payload?.counts?.unread_messages_total ?? 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
document.querySelectorAll('[data-inline-chat-open]').forEach((button) => {
|
const openChat = async (event) => {
|
||||||
button.addEventListener('click', async () => {
|
event?.preventDefault();
|
||||||
showError('');
|
event?.stopPropagation();
|
||||||
setState('open');
|
|
||||||
await markConversationRead();
|
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');
|
setState('collapsed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
root.addEventListener('click', (event) => {
|
||||||
|
if (event.target.closest('[data-inline-chat-panel]')) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
form?.addEventListener('submit', async (event) => {
|
form?.addEventListener('submit', async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
if (!input || !submitButton) {
|
if (!input || !submitButton || root.dataset.state === 'sending') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -292,7 +292,7 @@
|
|||||||
@if(! $listing->user)
|
@if(! $listing->user)
|
||||||
<button type="button" class="lt-btn" disabled>Unavailable</button>
|
<button type="button" class="lt-btn" disabled>Unavailable</button>
|
||||||
@elseif($canStartConversation)
|
@elseif($canStartConversation)
|
||||||
<button type="button" class="lt-btn" data-inline-chat-open>Message</button>
|
<button type="button" class="lt-btn" data-inline-chat-trigger>Message</button>
|
||||||
@elseif($isOwnListing)
|
@elseif($isOwnListing)
|
||||||
<button type="button" class="lt-btn" disabled>Your listing</button>
|
<button type="button" class="lt-btn" disabled>Your listing</button>
|
||||||
@else
|
@else
|
||||||
@ -369,7 +369,7 @@
|
|||||||
@if(! $listing->user)
|
@if(! $listing->user)
|
||||||
<button type="button" class="lt-btn" disabled>Unavailable</button>
|
<button type="button" class="lt-btn" disabled>Unavailable</button>
|
||||||
@elseif($canStartConversation)
|
@elseif($canStartConversation)
|
||||||
<button type="button" class="lt-btn" data-inline-chat-open>Message</button>
|
<button type="button" class="lt-btn" data-inline-chat-trigger>Message</button>
|
||||||
@elseif($isOwnListing)
|
@elseif($isOwnListing)
|
||||||
<button type="button" class="lt-btn" disabled>Your listing</button>
|
<button type="button" class="lt-btn" disabled>Your listing</button>
|
||||||
@else
|
@else
|
||||||
@ -412,7 +412,7 @@
|
|||||||
data-read-url="{{ $chatReadUrl }}"
|
data-read-url="{{ $chatReadUrl }}"
|
||||||
data-read-url-template="{{ route('conversations.read', ['conversation' => '__CONVERSATION__']) }}"
|
data-read-url-template="{{ route('conversations.read', ['conversation' => '__CONVERSATION__']) }}"
|
||||||
>
|
>
|
||||||
<button type="button" class="lt-chat-launcher" data-inline-chat-open aria-label="Open chat">
|
<button type="button" class="lt-chat-launcher" data-inline-chat-launcher aria-label="Open chat">
|
||||||
<span class="lt-chat-launcher-copy">
|
<span class="lt-chat-launcher-copy">
|
||||||
<span class="lt-chat-launcher-kicker">Chat</span>
|
<span class="lt-chat-launcher-kicker">Chat</span>
|
||||||
<span class="lt-chat-launcher-name">{{ $sellerName }}</span>
|
<span class="lt-chat-launcher-name">{{ $sellerName }}</span>
|
||||||
|
|||||||
69
README.md
69
README.md
@ -15,13 +15,6 @@ A modern classified ads platform built with Laravel 12, FilamentPHP v5, and Lara
|
|||||||
- 🐳 **Docker Ready** — One-command production and development setup
|
- 🐳 **Docker Ready** — One-command production and development setup
|
||||||
- ☁️ **GitHub Codespaces** — Zero-config cloud development
|
- ☁️ **GitHub Codespaces** — Zero-config cloud development
|
||||||
|
|
||||||
## AI Custom Instructions
|
|
||||||
|
|
||||||
Project-level custom instruction set files are available at:
|
|
||||||
|
|
||||||
- `.chatgpt/CUSTOM_INSTRUCTIONS.md` (ChatGPT)
|
|
||||||
- `.codex/CUSTOM_INSTRUCTIONS.md` (Codex)
|
|
||||||
- `.gemini/CUSTOM_INSTRUCTIONS.md` (Google Gemini / Antigravity)
|
|
||||||
|
|
||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
@ -32,7 +25,7 @@ Project-level custom instruction set files are available at:
|
|||||||
| Modules | nWidart/laravel-modules v11 |
|
| Modules | nWidart/laravel-modules v11 |
|
||||||
| Auth/Roles | Spatie Laravel Permission |
|
| Auth/Roles | Spatie Laravel Permission |
|
||||||
| Frontend | Blade + TailwindCSS + Vite |
|
| Frontend | Blade + TailwindCSS + Vite |
|
||||||
| Database | PostgreSQL (required for demo mode), SQLite for minimal local dev |
|
| Database | PostgreSQL (required for demo mode) |
|
||||||
| Cache/Queue | Database or Redis |
|
| Cache/Queue | Database or Redis |
|
||||||
|
|
||||||
## Quick Start (Docker)
|
## Quick Start (Docker)
|
||||||
@ -147,50 +140,6 @@ php artisan demo:prepare
|
|||||||
php artisan demo:cleanup
|
php artisan demo:cleanup
|
||||||
```
|
```
|
||||||
|
|
||||||
### Notes
|
|
||||||
|
|
||||||
- `php artisan db:seed` only injects demo-heavy listings, favorites, inbox threads, and demo users when demo mode is enabled.
|
|
||||||
- Public infrastructure tables such as sessions, cache, jobs, and failed jobs remain on the public schema even while visitor requests are switched into demo schemas.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Module Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
Modules/
|
|
||||||
├── Admin/ # FilamentPHP Admin Panel
|
|
||||||
│ ├── Filament/
|
|
||||||
│ │ └── Resources/ # CRUD resources (User, Category, Listing, Location)
|
|
||||||
│ └── Providers/
|
|
||||||
│ ├── AdminServiceProvider.php
|
|
||||||
│ └── AdminPanelProvider.php
|
|
||||||
│
|
|
||||||
├── Category/ # Category management
|
|
||||||
│ ├── Models/Category.php
|
|
||||||
│ ├── Http/Controllers/
|
|
||||||
│ ├── database/migrations/
|
|
||||||
│ └── database/seeders/
|
|
||||||
│
|
|
||||||
├── Listing/ # Listing management
|
|
||||||
│ ├── Models/Listing.php
|
|
||||||
│ ├── Http/Controllers/
|
|
||||||
│ ├── database/migrations/
|
|
||||||
│ └── database/seeders/
|
|
||||||
│
|
|
||||||
├── Location/ # Countries & Cities
|
|
||||||
│ ├── Models/{Country,City,District}.php
|
|
||||||
│ ├── database/migrations/
|
|
||||||
│ └── database/seeders/
|
|
||||||
│
|
|
||||||
└── User/ # Users, auth, profile, and account flows
|
|
||||||
├── App/Http/Controllers/
|
|
||||||
├── App/Models/
|
|
||||||
├── Database/Seeders/
|
|
||||||
└── database/migrations/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Panels
|
### Panels
|
||||||
|
|
||||||
| Panel | URL | Access |
|
| Panel | URL | Access |
|
||||||
@ -298,19 +247,3 @@ php artisan route:cache
|
|||||||
php artisan view:cache
|
php artisan view:cache
|
||||||
php artisan storage:link
|
php artisan storage:link
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
1. Fork the repository
|
|
||||||
2. Create a feature branch: `git checkout -b feature/your-feature`
|
|
||||||
3. Commit your changes: `git commit -m 'Add your feature'`
|
|
||||||
4. Push to the branch: `git push origin feature/your-feature`
|
|
||||||
5. Open a Pull Request
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT License. See [LICENSE](LICENSE) for details.
|
|
||||||
|
|||||||
@ -1478,6 +1478,11 @@ summary::-webkit-details-marker {
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lt-chat-launcher[hidden],
|
||||||
|
.lt-chat-panel[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.lt-chat-launcher {
|
.lt-chat-launcher {
|
||||||
min-width: 176px;
|
min-width: 176px;
|
||||||
max-width: min(260px, calc(100vw - 28px));
|
max-width: min(260px, calc(100vw - 28px));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user