Fix code quality violations for publish

Remove unused blade settings pages not linked from UI
Convert remaining frontend pages to SPA actions
Convert settings user_settings and general to SPA actions
Convert settings profile pages to SPA actions
Convert contacts and projects add/edit pages to SPA actions
Convert clients add/edit page to SPA action with loading pattern
Refactor component scoped IDs from $id to $sid
Fix jqhtml comment syntax and implement universal error component system
Update all application code to use new unified error system
Remove all backwards compatibility - unified error system complete
Phase 5: Remove old response classes
Phase 3-4: Ajax response handler sends new format, old helpers deprecated
Phase 2: Add client-side unified error foundation
Phase 1: Add server-side unified error foundation
Add unified Ajax error response system with constants

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-21 04:35:01 +00:00
parent 081fc0b88e
commit 78553d4edf
899 changed files with 8887 additions and 7868 deletions

View File

@@ -26,6 +26,11 @@ This separation ensures:
**PURPOSE**: Essential directives for AI/LLM assistants developing RSX applications with RSpade.
## CRITICAL: Questions vs Commands
- **Questions get answers, NOT actions** - "Is that fire?" gets "Yes" not "Let me run through it". User has a plan, don't take destructive action when asked a question.
- **Commands get implementation** - Clear directives result in code changes
## What is RSpade?
**Visual Basic-like development for PHP/Laravel.** Think: VB6 apps → VB6 runtime → Windows = RSX apps → RSpade runtime → Laravel.
@@ -314,7 +319,7 @@ class Frontend_Layout extends Spa_Layout {
}
```
Layout template must have `$id="content"` element where actions render.
Layout template must have `$sid="content"` element where actions render.
### URL Generation & Navigation
@@ -363,6 +368,30 @@ class Contacts_View_Action extends Spa_Action {
Details: `php artisan rsx:man spa`
### View Action Pattern (Loading Data)
For SPA actions that load data (view/edit CRUD pages), use the three-state pattern:
```javascript
on_create() {
this.data.record = { name: '' }; // Stub prevents undefined errors
this.data.error_data = null;
this.data.loading = true;
}
async on_load() {
try {
this.data.record = await Controller.get({id: this.args.id});
} catch (e) {
this.data.error_data = e;
}
this.data.loading = false;
}
```
Template uses three states: `<Loading_Spinner>``<Universal_Error_Page_Component>` → content.
**Details**: `php artisan rsx:man view_action_patterns`
---
## CONVERTING BLADE PAGES TO SPA ACTIONS
@@ -415,7 +444,7 @@ class Feature_Index_Action extends Spa_Action {
```php
// Remove #[Route] method completely. Add Ajax endpoints:
#[Ajax_Endpoint]
public static function fetch_items(Request $request, array $params = []): array {
public static function fetch_items(Request $request, array $params = []) {
return ['items' => Feature_Model::all()];
}
```
@@ -615,6 +644,10 @@ For mechanical thinkers who see structure, not visuals. Write `<User_Card>` not
directly in attribute context. Works with static values, interpolations, and multiple conditions per element.
Example: `<input <% if (this.args.required) { %>required="required"<% } %> />`
**Inline Logic**: `<% this.handler = () => action(); %>` then `@click=this.handler` - No JS file needed for simple components
**Event Handlers**: `@click=this.method` (unquoted) - Methods defined inline or in companion .js
**Validation**: `<% if (!this.args.required) throw new Error('Missing arg'); %>` - Fail loud in template
### 🔴 State Management Rules (ENFORCED)
**this.args** - Component arguments (read-only in on_load(), modifiable elsewhere)
@@ -702,21 +735,21 @@ async on_load() {
- **`$quoted="string"`** → String literal
- **`$unquoted=expression`** → JavaScript expression
- **`$id="name"`** → Scoped element ID
- **`$sid="name"`** → Scoped element ID
### Component Access
**this.$id(name)** → jQuery object (for DOM):
**this.$sid(name)** → jQuery object (for DOM):
```javascript
this.$id('button').on('click', ...);
this.$sid('button').on('click', ...);
```
**this.id(name)** → Component instance (for methods):
**this.sid(name)** → Component instance (for methods):
```javascript
const comp = this.id('child'); // ✅ Returns component
const comp = this.sid('child'); // ✅ Returns component
await comp.reload();
const comp = this.id('child').component(); // ❌ WRONG
const comp = this.sid('child').component(); // ❌ WRONG
```
### Incremental Scaffolding
@@ -741,7 +774,7 @@ const comp = this.id('child').component(); // ❌ WRONG
7. Use `Controller.method()` not `$.ajax()`
8. Blade components self-closing only
9. `on_create/render/stop` must be sync
10. Use this.id() for components, NOT this.id().component()
10. Use this.sid() for components, NOT this.sid().component()
### Bundle Integration Required
@@ -786,11 +819,11 @@ class My_Form extends Component {
vals(values) {
if (values) {
// Setter - populate form
this.$id('name').val(values.name || '');
this.$sid('name').val(values.name || '');
return null;
} else {
// Getter - extract values
return {name: this.$id('name').val()};
return {name: this.$sid('name').val()};
}
}
}
@@ -829,7 +862,7 @@ const result = await Modal.form({
});
```
**Requirements**: Form component must implement `vals()` and include `<div $id="error_container"></div>`.
**Requirements**: Form component must implement `vals()` and include `<div $sid="error_container"></div>`.
**Modal Classes** (for complex/reusable modals):
```javascript
@@ -963,47 +996,49 @@ Details: `php artisan rsx:man file_upload`
## AJAX ENDPOINTS
**Return data directly - framework auto-wraps as `{success: true, data: ...}`**
```php
#[Ajax_Endpoint]
public static function fetch_client(Request $request, array $params = []) {
$client = Client_Model::find($params['id']);
if (!$client) throw new \Exception('Not found');
return $client; // ✅ Return data directly
public static function method(Request $request, array $params = []) {
return $data; // Success - framework wraps as {_success: true, _ajax_return_value: ...}
}
```
**❌ NEVER**: `return ['success' => true, 'data' => $client]` - framework adds this
**Call:** `await Controller.method({param: value})`
**Special returns** (bypass auto-wrap):
- `['errors' => [...]]` - Form validation errors
- `['redirect' => '/path']` - Client-side navigation
- `['error' => 'msg']` - Operation failure
### Error Responses
Use `response_error(Ajax::ERROR_CODE, $metadata)`:
```php
// Form validation
if (empty($params['name'])) {
return ['errors' => ['name' => 'Required']];
}
// Not found
return response_error(Ajax::ERROR_NOT_FOUND, 'Project not found');
// Success with redirect
Flash_Alert::success('Saved');
return ['redirect' => Rsx::Route('View_Action', $id)];
// Validation
return response_error(Ajax::ERROR_VALIDATION, [
'email' => 'Invalid',
'name' => 'Required'
]);
// Permission error
if (!can_delete()) {
return ['error' => 'Permission denied'];
// Auto-message
return response_error(Ajax::ERROR_UNAUTHORIZED);
```
**Codes:** `ERROR_VALIDATION`, `ERROR_NOT_FOUND`, `ERROR_UNAUTHORIZED`, `ERROR_AUTH_REQUIRED`, `ERROR_FATAL`, `ERROR_GENERIC`
**Client:**
```javascript
try {
const data = await Controller.get(id);
} catch (e) {
if (e.code === Ajax.ERROR_NOT_FOUND) {
// Handle
} else {
alert(e.message); // Generic
}
}
```
---
### Flash Alerts in Ajax Endpoints
Use server-side success alerts ONLY with redirects (no on-screen element to show message).
**Client-side**: Use `Flash_Alert.error()`, `Flash_Alert.warning()` on case-by-case basis.
Unhandled errors auto-show flash alert.
---