docs(03): create phase 3 plans
Phase 3: Job Management Core - 4 plans created - 8 total tasks defined - Ready for execution Plans: - 03-01: Job submission form (Formidable + ACF) - 03-02: Job edit form with ownership validation - 03-03: Admin email notification on submission - 03-04: Admin moderation UI enhancements Parallelization: - Wave 1: 03-01, 03-02, 03-04 (independent) - Wave 2: 03-03 (depends on 03-01)
This commit is contained in:
216
.planning/phases/03-job-management-core/03-01-PLAN.md
Normal file
216
.planning/phases/03-job-management-core/03-01-PLAN.md
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 01
|
||||||
|
type: execute
|
||||||
|
depends_on: []
|
||||||
|
files_modified: [includes/class-formidable.php]
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Create Formidable Forms job submission form that creates job_offer posts with pending status.
|
||||||
|
|
||||||
|
Purpose: Enable providers to submit job listings through a frontend form. All submissions go to pending status for admin approval (core value: moderation before publication).
|
||||||
|
Output: Functional job submission form accessible to logged-in providers, creating job_offer posts with ACF fields populated.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
~/.claude/get-shit-done/workflows/execute-plan.md
|
||||||
|
~/.claude/get-shit-done/templates/summary.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/ROADMAP.md
|
||||||
|
@.planning/STATE.md
|
||||||
|
@.planning/phases/01-foundation-setup/01-03-SUMMARY.md
|
||||||
|
@.planning/phases/02-provider-registration-auth/02-01-SUMMARY.md
|
||||||
|
@includes/class-formidable.php
|
||||||
|
@includes/class-acf-fields.php
|
||||||
|
@includes/class-post-types.php
|
||||||
|
|
||||||
|
**Tech stack available:** Formidable Forms Pro (with Post Creation), ACF Pro, job_offer CPT
|
||||||
|
**Established patterns:** Programmatic Formidable form creation (from 02-01)
|
||||||
|
**Constraining decisions:**
|
||||||
|
- Jobs must submit to pending status (Phase 01-03)
|
||||||
|
- German labels for all form fields (PROJECT.md)
|
||||||
|
- ACF fields: job_location, job_type, job_deadline, job_contact_email, job_logo (Phase 01-03)
|
||||||
|
- Form key pattern for easy retrieval (established in 02-01)
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Create Formidable job submission form with ACF field mapping</name>
|
||||||
|
<files>includes/class-formidable.php</files>
|
||||||
|
<action>
|
||||||
|
Add `create_job_submission_form()` method to DDHH_JM_Formidable class. Programmatically create Formidable form with key 'job_submission' containing:
|
||||||
|
|
||||||
|
**Form Fields (all German labels):**
|
||||||
|
1. job_title (text, required) - "Stellentitel"
|
||||||
|
2. job_description (textarea, required) - "Stellenbeschreibung"
|
||||||
|
3. job_location (text, required) - "Standort"
|
||||||
|
4. job_type (select, required) - "Art" with choices: Vollzeit, Teilzeit, Ehrenamt
|
||||||
|
5. job_deadline (date, optional) - "Bewerbungsfrist" (format: d.m.Y)
|
||||||
|
6. job_contact_email (email, required) - "Kontakt-E-Mail"
|
||||||
|
7. job_logo (file upload, optional) - "Logo" (accept: image/jpeg, image/png, max: 2MB)
|
||||||
|
|
||||||
|
**Form Actions:**
|
||||||
|
- Create Post action configured to:
|
||||||
|
- Post type: 'job_offer'
|
||||||
|
- Post status: 'pending' (CRITICAL - enforces admin approval)
|
||||||
|
- Post title: mapped to job_title field
|
||||||
|
- Post content: mapped to job_description field
|
||||||
|
- Post author: current logged-in user (providers own their jobs)
|
||||||
|
- Custom field mappings to ACF fields:
|
||||||
|
- job_location → meta:job_location
|
||||||
|
- job_type → meta:job_type
|
||||||
|
- job_deadline → meta:job_deadline
|
||||||
|
- job_contact_email → meta:job_contact_email
|
||||||
|
- job_logo → meta:job_logo (as attachment ID)
|
||||||
|
|
||||||
|
**Form Settings:**
|
||||||
|
- Submit button text: "Stellenangebot einreichen"
|
||||||
|
- Success message: "Ihr Stellenangebot wurde zur Prüfung eingereicht!"
|
||||||
|
- Success action: Redirect to provider dashboard (/anbieter-dashboard/)
|
||||||
|
- Form description: "Alle Felder mit * sind Pflichtfelder. Ihr Angebot wird vor Veröffentlichung geprüft."
|
||||||
|
|
||||||
|
Add `get_job_submission_form_id()` helper method similar to `get_registration_form_id()`.
|
||||||
|
|
||||||
|
Hook form creation into existing `setup_registration_hooks()` or create separate `setup_job_forms_hooks()` if cleaner.
|
||||||
|
|
||||||
|
AVOID creating duplicate forms - check if form with key 'job_submission' exists before creating.
|
||||||
|
WHY: Prevents multiple identical forms in Formidable admin on plugin re-activation.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Check form exists: In WP-Admin → Formidable → Forms, verify form titled "Stellenangebot einreichen" exists
|
||||||
|
2. Check field count: Form should have 7 fields total
|
||||||
|
3. Check form action: Form should have "Create Post" action set to post_type='job_offer', status='pending'
|
||||||
|
4. PHP syntax: php -l includes/class-formidable.php (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Formidable form created programmatically with key 'job_submission'
|
||||||
|
- All 7 fields present with German labels
|
||||||
|
- Create Post action configured with pending status
|
||||||
|
- ACF field mappings complete
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Add form to provider dashboard with access control</name>
|
||||||
|
<files>templates/provider-dashboard.php</files>
|
||||||
|
<action>
|
||||||
|
Add job submission form to provider dashboard template above the job listings table.
|
||||||
|
|
||||||
|
**Structure:**
|
||||||
|
```php
|
||||||
|
<div class="ddhh-job-submit-section">
|
||||||
|
<h2>Neues Stellenangebot erstellen</h2>
|
||||||
|
<?php
|
||||||
|
$form_id = DDHH_JM_Formidable::get_job_submission_form_id();
|
||||||
|
if ( $form_id ) {
|
||||||
|
echo do_shortcode( "[formidable id={$form_id}]" );
|
||||||
|
} else {
|
||||||
|
echo '<p>Formular konnte nicht geladen werden.</p>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ddhh-job-listings-section">
|
||||||
|
<h2>Meine Stellenangebote</h2>
|
||||||
|
<!-- existing job listings table -->
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Styling (add to existing <style> block):**
|
||||||
|
- .ddhh-job-submit-section: margin-bottom: 3rem, padding: 2rem, background: #f5f5f5, border-radius: 8px
|
||||||
|
- Form should be visually distinct from job listings table
|
||||||
|
|
||||||
|
AVOID adding shortcode if form doesn't exist - check $form_id first.
|
||||||
|
WHY: Prevents errors if Formidable Forms is deactivated.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Template file updated with submission form section
|
||||||
|
2. Form appears above job listings table
|
||||||
|
3. Visual separation between form and listings
|
||||||
|
4. php -l templates/provider-dashboard.php (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Dashboard template includes job submission form
|
||||||
|
- Form section visually separated from listings
|
||||||
|
- Graceful fallback if form doesn't exist
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
Before declaring plan complete:
|
||||||
|
- [ ] Form 'job_submission' exists in Formidable Forms
|
||||||
|
- [ ] Form has 7 fields with German labels
|
||||||
|
- [ ] Create Post action configured with post_type='job_offer', status='pending'
|
||||||
|
- [ ] ACF fields mapped correctly in form action
|
||||||
|
- [ ] Form appears on provider dashboard at /anbieter-dashboard/
|
||||||
|
- [ ] No PHP syntax errors in modified files
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
|
||||||
|
- All tasks completed
|
||||||
|
- Job submission form functional
|
||||||
|
- Form creates job_offer posts with pending status
|
||||||
|
- ACF fields populated from form submission
|
||||||
|
- Form accessible on provider dashboard
|
||||||
|
- Ready for Plan 03-02 (edit form)
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/03-job-management-core/03-01-SUMMARY.md` with:
|
||||||
|
|
||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 01
|
||||||
|
subsystem: job-submission
|
||||||
|
tags: [formidable, job-creation, post-creation, acf-mapping]
|
||||||
|
requires: [01-03, 02-01]
|
||||||
|
provides: [job-submission-form]
|
||||||
|
affects: [03-03]
|
||||||
|
tech-stack:
|
||||||
|
added: [formidable-post-creation]
|
||||||
|
patterns: [post-creation-action, acf-field-mapping]
|
||||||
|
key-files:
|
||||||
|
modified: [includes/class-formidable.php, templates/provider-dashboard.php]
|
||||||
|
key-decisions: []
|
||||||
|
issues-created: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 3 Plan 1: Job Submission Form Summary
|
||||||
|
|
||||||
|
**[Substantive one-liner - what shipped]**
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- [Key outcomes]
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `includes/class-formidable.php` - [description]
|
||||||
|
- `templates/provider-dashboard.php` - [description]
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
[Form structure, field mappings, post creation action configuration]
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
[Any implementation choices, or "None"]
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
[Problems and resolutions, or "None"]
|
||||||
|
|
||||||
|
## Next Step
|
||||||
|
|
||||||
|
Ready for 03-02-PLAN.md (job edit form)
|
||||||
|
</output>
|
||||||
248
.planning/phases/03-job-management-core/03-02-PLAN.md
Normal file
248
.planning/phases/03-job-management-core/03-02-PLAN.md
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 02
|
||||||
|
type: execute
|
||||||
|
depends_on: []
|
||||||
|
files_modified: [includes/class-formidable.php, templates/provider-dashboard.php]
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Create Formidable Forms job edit form with ownership validation to prevent providers from editing others' jobs.
|
||||||
|
|
||||||
|
Purpose: Enable providers to update their own job listings. Security is critical - providers must only edit jobs they own.
|
||||||
|
Output: Functional job edit form with strict ownership checks, pre-populated with existing job data.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
~/.claude/get-shit-done/workflows/execute-plan.md
|
||||||
|
~/.claude/get-shit-done/templates/summary.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/ROADMAP.md
|
||||||
|
@.planning/STATE.md
|
||||||
|
@.planning/phases/01-foundation-setup/01-03-SUMMARY.md
|
||||||
|
@.planning/phases/02-provider-registration-auth/02-01-SUMMARY.md
|
||||||
|
@includes/class-formidable.php
|
||||||
|
@includes/class-acf-fields.php
|
||||||
|
@includes/class-post-types.php
|
||||||
|
@templates/provider-dashboard.php
|
||||||
|
|
||||||
|
**Tech stack available:** Formidable Forms Pro (with Update Post action), ACF Pro, job_offer CPT
|
||||||
|
**Established patterns:** Programmatic Formidable form creation, ACF field mapping
|
||||||
|
**Constraining decisions:**
|
||||||
|
- Providers can only edit their own jobs (security requirement)
|
||||||
|
- German labels for all form fields
|
||||||
|
- ACF fields: job_location, job_type, job_deadline, job_contact_email, job_logo
|
||||||
|
- Edit link in dashboard table (established in 02-03)
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Create job edit form with ownership validation</name>
|
||||||
|
<files>includes/class-formidable.php</files>
|
||||||
|
<action>
|
||||||
|
Add `create_job_edit_form()` method to DDHH_JM_Formidable class. Programmatically create Formidable form with key 'job_edit' containing:
|
||||||
|
|
||||||
|
**Form Fields (identical to submission form):**
|
||||||
|
1. job_title (text, required) - "Stellentitel"
|
||||||
|
2. job_description (textarea, required) - "Stellenbeschreibung"
|
||||||
|
3. job_location (text, required) - "Standort"
|
||||||
|
4. job_type (select, required) - "Art" with choices: Vollzeit, Teilzeit, Ehrenamt
|
||||||
|
5. job_deadline (date, optional) - "Bewerbungsfrist" (format: d.m.Y)
|
||||||
|
6. job_contact_email (email, required) - "Kontakt-E-Mail"
|
||||||
|
7. job_logo (file upload, optional) - "Logo" (accept: image/jpeg, image/png, max: 2MB)
|
||||||
|
|
||||||
|
**Form Configuration:**
|
||||||
|
- Edit mode: Load data from post ID passed via URL parameter (e.g., ?job_id=123)
|
||||||
|
- Form action: "Update Post" (not Create Post)
|
||||||
|
- Update target: Post ID from URL parameter
|
||||||
|
- Field pre-population: Load existing values from post and ACF fields
|
||||||
|
|
||||||
|
**Form Actions:**
|
||||||
|
- Update Post action configured to:
|
||||||
|
- Post ID source: URL parameter 'job_id'
|
||||||
|
- Post type: 'job_offer'
|
||||||
|
- Post title: mapped to job_title field
|
||||||
|
- Post content: mapped to job_description field
|
||||||
|
- Custom field mappings (same as submission form):
|
||||||
|
- job_location → meta:job_location
|
||||||
|
- job_type → meta:job_type
|
||||||
|
- job_deadline → meta:job_deadline
|
||||||
|
- job_contact_email → meta:job_contact_email
|
||||||
|
- job_logo → meta:job_logo
|
||||||
|
|
||||||
|
**Ownership Validation Hook:**
|
||||||
|
Create `validate_job_ownership()` method that hooks into `frm_validate_entry` filter:
|
||||||
|
- Check if job_id URL parameter exists
|
||||||
|
- Verify post_type is 'job_offer'
|
||||||
|
- Verify post_author matches current user ID
|
||||||
|
- If validation fails: add Formidable error "Sie haben keine Berechtigung, dieses Stellenangebot zu bearbeiten."
|
||||||
|
- CRITICAL security check - prevents URL parameter tampering
|
||||||
|
|
||||||
|
**Form Settings:**
|
||||||
|
- Submit button text: "Änderungen speichern"
|
||||||
|
- Success message: "Ihre Änderungen wurden gespeichert!"
|
||||||
|
- Success action: Redirect to provider dashboard (/anbieter-dashboard/)
|
||||||
|
|
||||||
|
Add `get_job_edit_form_id()` helper method.
|
||||||
|
|
||||||
|
AVOID trusting URL parameters without ownership validation.
|
||||||
|
WHY: Security risk - malicious providers could edit others' jobs by changing URL parameter.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Form exists: Check Formidable admin for form with key 'job_edit'
|
||||||
|
2. Ownership validation: Check `validate_job_ownership()` method exists and hooks into `frm_validate_entry`
|
||||||
|
3. Update action: Form should have "Update Post" action, not "Create Post"
|
||||||
|
4. PHP syntax: php -l includes/class-formidable.php (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Edit form created with key 'job_edit'
|
||||||
|
- All fields present and pre-populate from existing post
|
||||||
|
- Update Post action configured
|
||||||
|
- Ownership validation hook implemented
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Update dashboard edit links to use edit form</name>
|
||||||
|
<files>templates/provider-dashboard.php</files>
|
||||||
|
<action>
|
||||||
|
Update the "Edit" action link in the dashboard job listings table to point to the edit form.
|
||||||
|
|
||||||
|
**Current state:** Edit link likely points to WP edit post screen (providers can't access)
|
||||||
|
**New state:** Edit link points to edit form on dashboard with job_id parameter
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
Update the edit link generation in the jobs table:
|
||||||
|
```php
|
||||||
|
// OLD (if exists):
|
||||||
|
$edit_url = get_edit_post_link( $job->ID );
|
||||||
|
|
||||||
|
// NEW:
|
||||||
|
$edit_url = add_query_arg(
|
||||||
|
array(
|
||||||
|
'action' => 'edit_job',
|
||||||
|
'job_id' => $job->ID
|
||||||
|
),
|
||||||
|
get_permalink( get_option( 'ddhh_jm_dashboard_page_id' ) )
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Add form display logic before or after the listings table:
|
||||||
|
```php
|
||||||
|
// Check if we're in edit mode
|
||||||
|
if ( isset( $_GET['action'] ) && $_GET['action'] === 'edit_job' && isset( $_GET['job_id'] ) ) {
|
||||||
|
$job_id = absint( $_GET['job_id'] );
|
||||||
|
$form_id = DDHH_JM_Formidable::get_job_edit_form_id();
|
||||||
|
|
||||||
|
if ( $form_id ) {
|
||||||
|
echo '<div class="ddhh-job-edit-section">';
|
||||||
|
echo '<h2>Stellenangebot bearbeiten</h2>';
|
||||||
|
echo '<p><a href="' . get_permalink() . '">← Zurück zur Übersicht</a></p>';
|
||||||
|
echo do_shortcode( "[formidable id={$form_id}]" );
|
||||||
|
echo '</div>';
|
||||||
|
|
||||||
|
// Don't show listings table when editing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show normal dashboard (submission form + listings) if not editing
|
||||||
|
```
|
||||||
|
|
||||||
|
AVOID displaying both edit form and listings simultaneously - show one or the other.
|
||||||
|
WHY: Confusing UX, wastes screen space, makes page too long.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Edit links updated to use ?action=edit_job&job_id=X format
|
||||||
|
2. Edit form displays when clicking edit link
|
||||||
|
3. Listings table hidden when editing
|
||||||
|
4. Back link present to return to dashboard
|
||||||
|
5. php -l templates/provider-dashboard.php (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Edit links point to edit form with job_id parameter
|
||||||
|
- Edit form displays on dashboard when action=edit_job
|
||||||
|
- Listings hidden during edit mode
|
||||||
|
- Back navigation link present
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
Before declaring plan complete:
|
||||||
|
- [ ] Form 'job_edit' exists in Formidable Forms
|
||||||
|
- [ ] Ownership validation hook implemented in `frm_validate_entry`
|
||||||
|
- [ ] Edit form pre-populates with existing job data
|
||||||
|
- [ ] Edit links in dashboard table work correctly
|
||||||
|
- [ ] Providers cannot edit others' jobs (security validated)
|
||||||
|
- [ ] No PHP syntax errors in modified files
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
|
||||||
|
- All tasks completed
|
||||||
|
- Job edit form functional with ownership checks
|
||||||
|
- Dashboard integrates edit form properly
|
||||||
|
- Security validated - only own jobs editable
|
||||||
|
- Ready for Plan 03-03 (notifications)
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/03-job-management-core/03-02-SUMMARY.md` with:
|
||||||
|
|
||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 02
|
||||||
|
subsystem: job-editing
|
||||||
|
tags: [formidable, job-editing, post-update, security, ownership]
|
||||||
|
requires: [01-03, 02-03]
|
||||||
|
provides: [job-edit-form, ownership-validation]
|
||||||
|
affects: []
|
||||||
|
tech-stack:
|
||||||
|
added: [formidable-update-post]
|
||||||
|
patterns: [ownership-validation, pre-populated-forms]
|
||||||
|
key-files:
|
||||||
|
modified: [includes/class-formidable.php, templates/provider-dashboard.php]
|
||||||
|
key-decisions:
|
||||||
|
- Edit form validates ownership via frm_validate_entry hook
|
||||||
|
- Dashboard shows edit form OR listings, not both simultaneously
|
||||||
|
- Edit mode triggered by URL parameter action=edit_job
|
||||||
|
issues-created: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 3 Plan 2: Job Edit Form Summary
|
||||||
|
|
||||||
|
**[Substantive one-liner - what shipped]**
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- [Key outcomes including security validation]
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `includes/class-formidable.php` - [description]
|
||||||
|
- `templates/provider-dashboard.php` - [description]
|
||||||
|
|
||||||
|
## Security Implementation
|
||||||
|
|
||||||
|
[Details of ownership validation hook and how it prevents unauthorized edits]
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
[Implementation choices, or "None"]
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
[Problems and resolutions, or "None"]
|
||||||
|
|
||||||
|
## Next Step
|
||||||
|
|
||||||
|
Ready for 03-03-PLAN.md (admin notifications) or 03-04-PLAN.md (admin UI) - both can run in parallel
|
||||||
|
</output>
|
||||||
215
.planning/phases/03-job-management-core/03-03-PLAN.md
Normal file
215
.planning/phases/03-job-management-core/03-03-PLAN.md
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 03
|
||||||
|
type: execute
|
||||||
|
depends_on: ["03-01"]
|
||||||
|
files_modified: [includes/class-notifications.php, includes/class-ddhh-job-manager.php, ddhh-job-manager.php]
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Send email notification to site admin when a provider submits a new job listing for moderation.
|
||||||
|
|
||||||
|
Purpose: Alert admins immediately when new jobs require review, ensuring timely moderation (core value: admin approval before publication).
|
||||||
|
Output: Automated email notifications to admin on every new job submission.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
~/.claude/get-shit-done/workflows/execute-plan.md
|
||||||
|
~/.claude/get-shit-done/templates/summary.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/ROADMAP.md
|
||||||
|
@.planning/STATE.md
|
||||||
|
@.planning/phases/01-foundation-setup/01-03-SUMMARY.md
|
||||||
|
@.planning/phases/03-job-management-core/03-01-SUMMARY.md
|
||||||
|
@includes/class-formidable.php
|
||||||
|
@includes/class-post-types.php
|
||||||
|
|
||||||
|
**Tech stack available:** WordPress wp_mail(), Formidable post creation hooks, job_offer CPT
|
||||||
|
**Established patterns:** German text for user-facing content
|
||||||
|
**Constraining decisions:**
|
||||||
|
- Jobs submit to pending status (Phase 01-03)
|
||||||
|
- Admin moderation is core value (PROJECT.md)
|
||||||
|
- Email may be disabled in Local WP dev (PROJECT.md context)
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Create notification class with admin alert on job submission</name>
|
||||||
|
<files>includes/class-notifications.php</files>
|
||||||
|
<action>
|
||||||
|
Create new file `includes/class-notifications.php` with class `DDHH_JM_Notifications`.
|
||||||
|
|
||||||
|
**Method:** `send_admin_new_job_notification( $post_id )`
|
||||||
|
|
||||||
|
Hook into `transition_post_status` action to detect when a job_offer transitions to 'pending':
|
||||||
|
- Check: $new_status === 'pending' && $old_status !== 'pending' && $post->post_type === 'job_offer'
|
||||||
|
- Avoid sending on every save - only on initial submission to pending
|
||||||
|
|
||||||
|
**Email Content (German):**
|
||||||
|
- **To:** get_option('admin_email')
|
||||||
|
- **Subject:** "Neues Stellenangebot zur Prüfung: {job_title}"
|
||||||
|
- **Body:**
|
||||||
|
```
|
||||||
|
Ein neues Stellenangebot wurde eingereicht und wartet auf Ihre Prüfung.
|
||||||
|
|
||||||
|
Titel: {job_title}
|
||||||
|
Anbieter: {author_name} ({author_organization})
|
||||||
|
Standort: {job_location}
|
||||||
|
Art: {job_type}
|
||||||
|
Eingereicht am: {submission_date}
|
||||||
|
|
||||||
|
Prüfen Sie das Stellenangebot hier:
|
||||||
|
{edit_link}
|
||||||
|
|
||||||
|
---
|
||||||
|
Diese E-Mail wurde automatisch gesendet.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Email Details:**
|
||||||
|
- Use wp_mail() for sending
|
||||||
|
- Headers: 'Content-Type: text/html; charset=UTF-8'
|
||||||
|
- Edit link: get_edit_post_link( $post_id, '' ) - direct admin edit URL
|
||||||
|
- Author org: get_user_meta( $post->post_author, 'ddhh_org_name', true )
|
||||||
|
- ACF fields: get_field('job_location'), get_field('job_type')
|
||||||
|
- Date: get_the_date( 'd.m.Y H:i', $post_id )
|
||||||
|
|
||||||
|
**Setup method:** `setup_hooks()`
|
||||||
|
- Hook into 'transition_post_status' with priority 10, accepts 3 params
|
||||||
|
|
||||||
|
AVOID sending emails on every post update - only initial pending submission.
|
||||||
|
WHY: Prevents spam when admins save/update pending posts.
|
||||||
|
|
||||||
|
AVOID failing silently if wp_mail() fails - log errors.
|
||||||
|
WHY: Email issues are common (Local WP disables email), admins need visibility.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Class file created with proper structure
|
||||||
|
2. Hook registered in setup_hooks() method
|
||||||
|
3. Email sends only on new → pending transition
|
||||||
|
4. Email includes all required fields (title, author, location, type, edit link)
|
||||||
|
5. php -l includes/class-notifications.php (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Notification class created
|
||||||
|
- Admin email sent on new job submission
|
||||||
|
- Email content in German with all job details
|
||||||
|
- Transition hook properly configured
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Integrate notifications into plugin initialization</name>
|
||||||
|
<files>includes/class-ddhh-job-manager.php, ddhh-job-manager.php</files>
|
||||||
|
<action>
|
||||||
|
**File 1: ddhh-job-manager.php**
|
||||||
|
Add require statement for notifications class:
|
||||||
|
```php
|
||||||
|
require_once plugin_dir_path( __FILE__ ) . 'includes/class-notifications.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
**File 2: includes/class-ddhh-job-manager.php**
|
||||||
|
In the `__construct()` or initialization method, add hook for notifications:
|
||||||
|
```php
|
||||||
|
add_action( 'init', array( 'DDHH_JM_Notifications', 'setup_hooks' ) );
|
||||||
|
```
|
||||||
|
|
||||||
|
Pattern should match existing hook registrations (e.g., how DDHH_JM_Access_Control::setup_hooks is called from Phase 2).
|
||||||
|
|
||||||
|
AVOID hooking too early - use 'init' action for consistency with other classes.
|
||||||
|
WHY: Ensures all WordPress functions (wp_mail, ACF) are available when notification runs.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Require statement added to main plugin file
|
||||||
|
2. setup_hooks() called via init action in main class
|
||||||
|
3. Pattern consistent with other class initializations
|
||||||
|
4. php -l on both modified files (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Notifications class required in main plugin file
|
||||||
|
- Hooks initialized via init action
|
||||||
|
- Integration consistent with existing pattern
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
Before declaring plan complete:
|
||||||
|
- [ ] DDHH_JM_Notifications class exists
|
||||||
|
- [ ] Hook registered on transition_post_status
|
||||||
|
- [ ] Email sent only on new pending job submissions
|
||||||
|
- [ ] Email includes job title, author, location, type, edit link
|
||||||
|
- [ ] Email text in German
|
||||||
|
- [ ] Class integrated into plugin initialization
|
||||||
|
- [ ] No PHP syntax errors
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
|
||||||
|
- All tasks completed
|
||||||
|
- Admin email notification functional
|
||||||
|
- Email triggers only on new submissions (not updates)
|
||||||
|
- Email content complete and in German
|
||||||
|
- Ready for Plan 03-04 (admin UI)
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/03-job-management-core/03-03-SUMMARY.md` with:
|
||||||
|
|
||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 03
|
||||||
|
subsystem: notifications
|
||||||
|
tags: [email, admin-notification, wp-mail, post-transitions]
|
||||||
|
requires: [03-01]
|
||||||
|
provides: [admin-job-notification]
|
||||||
|
affects: []
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: [transition-post-status-hook, wp-mail-notifications]
|
||||||
|
key-files:
|
||||||
|
created: [includes/class-notifications.php]
|
||||||
|
modified: [includes/class-ddhh-job-manager.php, ddhh-job-manager.php]
|
||||||
|
key-decisions:
|
||||||
|
- Used transition_post_status to detect only initial pending submissions
|
||||||
|
- Email sent to admin_email option (site admin)
|
||||||
|
- Email includes edit link for quick access to moderation
|
||||||
|
issues-created: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 3 Plan 3: Admin Notifications Summary
|
||||||
|
|
||||||
|
**[Substantive one-liner - what shipped]**
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- [Key outcomes]
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `includes/class-notifications.php` - [description]
|
||||||
|
- `includes/class-ddhh-job-manager.php` - [description]
|
||||||
|
- `ddhh-job-manager.php` - [description]
|
||||||
|
|
||||||
|
## Email Template
|
||||||
|
|
||||||
|
[Copy of actual email content sent to admin]
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
[Implementation choices, or "None"]
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
[Problems and resolutions, or "None"]
|
||||||
|
|
||||||
|
## Next Step
|
||||||
|
|
||||||
|
Ready for 03-04-PLAN.md (admin UI enhancements) - can run in parallel with this plan
|
||||||
|
</output>
|
||||||
255
.planning/phases/03-job-management-core/03-04-PLAN.md
Normal file
255
.planning/phases/03-job-management-core/03-04-PLAN.md
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 04
|
||||||
|
type: execute
|
||||||
|
depends_on: []
|
||||||
|
files_modified: [includes/class-admin-ui.php, includes/class-ddhh-job-manager.php, ddhh-job-manager.php]
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Enhance WordPress admin interface for job moderation with custom columns, filters, and quick actions.
|
||||||
|
|
||||||
|
Purpose: Give admins efficient tools to moderate job submissions. Better visibility = faster moderation = core value delivered.
|
||||||
|
Output: Admin job listing with pending count badge, status filters, and provider info columns.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
~/.claude/get-shit-done/workflows/execute-plan.md
|
||||||
|
~/.claude/get-shit-done/templates/summary.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/ROADMAP.md
|
||||||
|
@.planning/STATE.md
|
||||||
|
@.planning/phases/01-foundation-setup/01-02-SUMMARY.md
|
||||||
|
@.planning/phases/01-foundation-setup/01-03-SUMMARY.md
|
||||||
|
@includes/class-post-types.php
|
||||||
|
@includes/class-acf-fields.php
|
||||||
|
|
||||||
|
**Tech stack available:** WordPress admin hooks, job_offer CPT, ACF fields
|
||||||
|
**Established patterns:** German labels for admin UI
|
||||||
|
**Constraining decisions:**
|
||||||
|
- Admin moderation is core workflow (PROJECT.md)
|
||||||
|
- Jobs start as pending (Phase 01-03)
|
||||||
|
- ACF fields available: job_location, job_type, job_contact_email
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Add custom admin columns for job moderation</name>
|
||||||
|
<files>includes/class-admin-ui.php</files>
|
||||||
|
<action>
|
||||||
|
Create new file `includes/class-admin-ui.php` with class `DDHH_JM_Admin_UI`.
|
||||||
|
|
||||||
|
**Custom Columns for job_offer post type:**
|
||||||
|
|
||||||
|
Hook into `manage_job_offer_posts_columns` filter to add columns:
|
||||||
|
1. **Anbieter** (Provider) - Organization name + contact person
|
||||||
|
2. **Standort** (Location) - job_location ACF field
|
||||||
|
3. **Art** (Type) - job_type ACF field
|
||||||
|
4. **Eingereicht am** (Submitted) - Post creation date
|
||||||
|
|
||||||
|
Remove default columns if cluttering:
|
||||||
|
- 'date' (replaced by custom "Eingereicht am")
|
||||||
|
- 'author' (replaced by custom "Anbieter" with org name)
|
||||||
|
|
||||||
|
Hook into `manage_job_offer_posts_custom_column` action to populate column data:
|
||||||
|
- **Anbieter:** Display `{org_name}<br><small>{contact_person}</small>` where org_name is user meta 'ddhh_org_name'
|
||||||
|
- **Standort:** get_field('job_location', $post_id)
|
||||||
|
- **Art:** get_field('job_type', $post_id)
|
||||||
|
- **Eingereicht am:** get_the_date('d.m.Y H:i', $post_id)
|
||||||
|
|
||||||
|
Make columns sortable via `manage_edit-job_offer_sortable_columns` filter (at minimum: Eingereicht am, Standort, Art).
|
||||||
|
|
||||||
|
AVOID cluttering admin with too many columns - remove non-essential defaults.
|
||||||
|
WHY: Admins need to see moderation-relevant info at a glance, not every detail.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Class file created with proper structure
|
||||||
|
2. Custom columns registered via manage_*_columns hooks
|
||||||
|
3. Column data populated correctly
|
||||||
|
4. Sortable columns work
|
||||||
|
5. php -l includes/class-admin-ui.php (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Admin columns added: Anbieter, Standort, Art, Eingereicht am
|
||||||
|
- Column data populated from user meta and ACF fields
|
||||||
|
- Sortable columns functional
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Add status filters and pending count badge</name>
|
||||||
|
<files>includes/class-admin-ui.php</files>
|
||||||
|
<action>
|
||||||
|
Add status filter links and pending count badge to admin job listing.
|
||||||
|
|
||||||
|
**Status Filters:**
|
||||||
|
Hook into `views_edit-job_offer` filter to add custom view links:
|
||||||
|
- All
|
||||||
|
- Pending (Ausstehend)
|
||||||
|
- Published (Veröffentlicht)
|
||||||
|
- Draft (Entwurf)
|
||||||
|
|
||||||
|
Each link should include count of posts in that status.
|
||||||
|
|
||||||
|
**Pending Count Badge:**
|
||||||
|
Add visual badge to "Pending" link using CSS class 'count':
|
||||||
|
```php
|
||||||
|
$pending_count = wp_count_posts('job_offer')->pending;
|
||||||
|
$views['pending'] = sprintf(
|
||||||
|
'<a href="%s">%s <span class="count">(%d)</span></a>',
|
||||||
|
admin_url('edit.php?post_type=job_offer&post_status=pending'),
|
||||||
|
__('Ausstehend', 'ddhh-job-manager'),
|
||||||
|
$pending_count
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Make "Pending" link prominent if count > 0 - admins should see it immediately.
|
||||||
|
|
||||||
|
**Quick Actions:**
|
||||||
|
Keep default WordPress quick actions (Edit, Quick Edit, Trash) - don't remove.
|
||||||
|
Consider adding custom "Approve" quick action that publishes post directly:
|
||||||
|
- Link: wp_nonce_url with action 'approve_job'
|
||||||
|
- Handler: Check nonce, verify user is admin, update post_status to 'publish'
|
||||||
|
- Optional but helpful for one-click approval
|
||||||
|
|
||||||
|
AVOID removing WordPress's built-in quick actions - admins expect them.
|
||||||
|
WHY: Standard WordPress UX, admins are familiar with Edit/Trash.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Status filter links present in admin
|
||||||
|
2. Pending count badge shows correct number
|
||||||
|
3. Filters work correctly when clicked
|
||||||
|
4. Quick actions functional
|
||||||
|
5. php -l includes/class-admin-ui.php (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Status filter links added with counts
|
||||||
|
- Pending badge visible and accurate
|
||||||
|
- Filters functional
|
||||||
|
- Quick actions preserved (Edit, Trash, etc.)
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 3: Integrate admin UI enhancements into plugin</name>
|
||||||
|
<files>includes/class-ddhh-job-manager.php, ddhh-job-manager.php</files>
|
||||||
|
<action>
|
||||||
|
**File 1: ddhh-job-manager.php**
|
||||||
|
Add require statement:
|
||||||
|
```php
|
||||||
|
require_once plugin_dir_path( __FILE__ ) . 'includes/class-admin-ui.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
**File 2: includes/class-ddhh-job-manager.php**
|
||||||
|
Initialize admin UI hooks (admin-only):
|
||||||
|
```php
|
||||||
|
if ( is_admin() ) {
|
||||||
|
add_action( 'init', array( 'DDHH_JM_Admin_UI', 'setup_hooks' ) );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `setup_hooks()` static method in DDHH_JM_Admin_UI class that registers all admin hooks:
|
||||||
|
- manage_job_offer_posts_columns
|
||||||
|
- manage_job_offer_posts_custom_column
|
||||||
|
- manage_edit-job_offer_sortable_columns
|
||||||
|
- views_edit-job_offer
|
||||||
|
|
||||||
|
AVOID loading admin hooks on frontend - check is_admin().
|
||||||
|
WHY: Performance - frontend doesn't need admin column logic.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Require statement added to main plugin file
|
||||||
|
2. Admin UI hooks initialized only in admin
|
||||||
|
3. setup_hooks() method exists in DDHH_JM_Admin_UI
|
||||||
|
4. php -l on both files (no errors)
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
- Admin UI class required
|
||||||
|
- Hooks initialized (admin-only)
|
||||||
|
- Integration complete
|
||||||
|
- No PHP syntax errors
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
Before declaring plan complete:
|
||||||
|
- [ ] Custom admin columns visible in job_offer listing
|
||||||
|
- [ ] Column data accurate (provider org, location, type, date)
|
||||||
|
- [ ] Status filters functional
|
||||||
|
- [ ] Pending count badge shows correct number
|
||||||
|
- [ ] Sortable columns work
|
||||||
|
- [ ] Only loads in admin (not frontend)
|
||||||
|
- [ ] No PHP syntax errors
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
|
||||||
|
- All tasks completed
|
||||||
|
- Admin moderation UI enhanced
|
||||||
|
- Custom columns provide visibility
|
||||||
|
- Status filters aid workflow
|
||||||
|
- Phase 3 complete - ready for Phase 4
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/03-job-management-core/03-04-SUMMARY.md` with:
|
||||||
|
|
||||||
|
---
|
||||||
|
phase: 03-job-management-core
|
||||||
|
plan: 04
|
||||||
|
subsystem: admin-ui
|
||||||
|
tags: [admin, moderation, columns, filters, wordpress-admin]
|
||||||
|
requires: [01-02, 01-03]
|
||||||
|
provides: [admin-job-columns, status-filters]
|
||||||
|
affects: []
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: [admin-columns, admin-filters, sortable-columns]
|
||||||
|
key-files:
|
||||||
|
created: [includes/class-admin-ui.php]
|
||||||
|
modified: [includes/class-ddhh-job-manager.php, ddhh-job-manager.php]
|
||||||
|
key-decisions:
|
||||||
|
- Removed default 'author' and 'date' columns in favor of custom ones
|
||||||
|
- Pending count badge for visibility
|
||||||
|
- Admin-only hook loading for performance
|
||||||
|
issues-created: []
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 3 Plan 4: Admin Moderation UI Summary
|
||||||
|
|
||||||
|
**[Substantive one-liner - what shipped]**
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- [Key outcomes]
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `includes/class-admin-ui.php` - [description]
|
||||||
|
- `includes/class-ddhh-job-manager.php` - [description]
|
||||||
|
- `ddhh-job-manager.php` - [description]
|
||||||
|
|
||||||
|
## Admin Interface Changes
|
||||||
|
|
||||||
|
[Screenshot or description of new columns, filters, badges]
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
[Implementation choices, or "None"]
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
[Problems and resolutions, or "None"]
|
||||||
|
|
||||||
|
## Next Step
|
||||||
|
|
||||||
|
Phase 3 complete. Ready for Phase 4: Job Deactivation System
|
||||||
|
</output>
|
||||||
Reference in New Issue
Block a user