Date field shows as '20260130' instead of German format '30.01.2026'. Documented as low priority cosmetic issue to be fixed later.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added edit_published_job_offers capability to ddhh_provider role and created upgrade_roles function to automatically add this capability to existing provider accounts. Providers can now edit their published job offers from the dashboard.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created DDHH_JM_Template class to display full job details on single job offer pages. Shows logo, organization, location, type, deadline, description, and contact information in a styled layout.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Moved job submission notifications from transition_post_status hook to custom ddhh_job_submitted/ddhh_job_edited hooks. This ensures metadata is saved before the email is sent, so location and type fields are populated correctly instead of showing "Nicht angegeben".
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Adds comprehensive job submission, editing, and deactivation functionality with proper form handling and permissions. Includes administrator capabilities for job_offer management and fixed dashboard navigation.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Job submission form had 0 actions, posts weren't being created
- Manually created wppost action with proper field mappings
- Maps all 7 fields (title, description, location, type, deadline, email, logo)
- Discovered during provider flow testing (jobs not appearing in dashboard)
- Logo field misplaced on job form instead of provider profile
- Empty dropdown issue (fixed)
- Identified required changes for proper company logo implementation
- Added ddhhRedirectTriggered flag to ensure only one redirect
- Clear interval immediately when success message detected
- Removed MutationObserver which was causing duplicate events
- Simplified JavaScript to single interval-based check
- Changed from event listener to MutationObserver
- Watches for success message text to appear in form
- Monitors form DOM for changes and redirects when success appears
- More reliable than waiting for custom events
- Added set_registration_redirect() filter on frm_json_response
- Modifies Formidable's JSON response to include redirect_url
- Formidable JavaScript will then redirect to /anbieter-dashboard/
- Fixes registration redirect issue
- Registration form now redirects to /anbieter-dashboard/ after successful submission
- Configured via form options redirect_url setting
- Fixes missing redirect after registration
- Changed !== to != to allow type coercion
- Fixes registration not working due to string vs int comparison
- Added type debugging to help diagnose similar issues
- Changed FrmFormAction::create() to FrmFormActionsController::create_action()
- Updated class_exists checks to use FrmFormActionsController
- Fixes fatal error on plugin activation with modern Formidable Forms
- Discovered during provider flow testing (Plan 07-01)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Phase 6 Plan 3 complete. Async batch email notifications to opted-in
mentors on job publish without blocking admin workflow. Integrated with
Action Scheduler for background processing in batches of 50 users.
German email templates with job details, rate limit delays, error
logging, and unsubscribe hints.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add process_mentor_notification_batch() method to process Action
Scheduler callbacks. Sends German email notifications with job details
(title, location, type, permalink) to batches of opted-in mentors.
Includes rate limit delay (0.1s between emails), error logging for
failures, and unsubscribe hint in email body. Registered callback for
'ddhh_jm_send_mentor_notification_batch' hook.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add notify_mentors_on_job_publish() method to trigger async batch
notifications when jobs transition to publish status. Only triggers on
initial publish (not updates). Queries opted-in mentors via User
Preferences class and schedules batches via Scheduler class. Logs
notification scheduling with mentor count and batch count.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Tasks completed: 2/2
- User preferences class with notification opt-in meta
- Helper method to query opted-in mentors
SUMMARY: .planning/phases/06-email-notifications/06-01-SUMMARY.md
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Created DDHH_JM_Scheduler class with static setup_hooks() method
- Added schedule_mentor_notification_batch() method with 50-user batching
- Uses as_enqueue_async_action() with unique flag and email-notifications group
- Initialized in main plugin file and job manager class
- Ready for Phase 06-03 to register async action callbacks
- Downloaded Action Scheduler 3.9.3 from GitHub
- Placed in vendor/action-scheduler/ directory
- Included in main plugin file before other code for proper initialization
- Library will auto-initialize itself when required
Summary documents single job post access control implementation,
completing Phase 5 backend infrastructure. Elementor template creation
is manual UI work through WordPress admin.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add protect_single_job() method to access control class following the
same pattern as job archive protection. Non-logged-in users are
redirected to /anbieter-login/ when attempting to access individual
job_offer posts. Logged-in users (any role) can view job details.
Completes backend infrastructure for Phase 5 mentor job board. All ACF
fields and application form ready for Elementor template integration.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add send_provider_application_notification() method:
- Hooks to frm_after_create_entry for job application form submissions
- Extracts applicant details (name, email, message) and job_id
- Fetches job details (title, location, type) from post and ACF fields
- Sends email to provider contact email (job_contact_email ACF field)
- Email includes full applicant info and job context
- Provider can reply directly to applicant email
- Error logging for missing contact email or wp_mail failures
Hook registered in setup_hooks() method
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add DDHH_JM_Archive class to modify job archive queries. Ensures
Elementor Loop Grid displays only published jobs sorted by date
(newest first) with no pagination limit.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add create_job_application_form() method with 4 fields:
- applicant_name (text, required)
- applicant_email (email, required, pre-filled for logged-in users)
- applicant_message (textarea, required)
- job_id (hidden)
Form title: "Jetzt bewerben"
Submit button: "Bewerbung absenden"
Success message: "Ihre Bewerbung wurde versendet. Der Anbieter wird sich bei Ihnen melden."
Added get_job_application_form_id() helper method
Registered form creation in setup_registration_hooks()
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add register_image_sizes() method to DDHH_JM_Post_Types class that
registers 'job-logo' image size (200x200px with hard crop). Hook
method to after_setup_theme action for proper WordPress timing.
This enables Elementor templates to request consistent logo sizing
via wp_get_attachment_image() using size 'job-logo'. Auto-generates
cropped version when logos uploaded via ACF field.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Protect job archive from public access by redirecting non-logged-in users
to /anbieter-login/. Only authenticated users (mentors/subscribers) can
browse the /jobangebote/ archive.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Phase 05: Mentor Job Board
- 3 plans created (parallel-ready)
- 5 total tasks defined
- Ready for execution
Plans:
- 05-01: Archive access control and query setup
- 05-02: Job application form with provider notification
- 05-03: Logo auto-crop to 200x200px
All plans independent (depends_on: []), can execute in parallel.
- Added send_admin_job_deactivation_notification() method
- Hooks transition_post_status with guards: draft status AND old publish
- Extracts deactivation reason from ACF field job_deactivation_reason
- Email subject: "Stellenangebot deaktiviert: {job_title}"
- Email includes job details, provider info, and deactivation reason
- Sends to admin_email with edit link for review
- Error logging for missing admin_email or wp_mail failure
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Create SUMMARY.md documenting completed plan 04-01: job deactivation form with required reason field, ownership validation, and dashboard integration. Update STATE.md to reflect Phase 4 Plan 1 completion (12 plans total, 48% progress). Update ROADMAP.md to mark 04-01 as complete.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add deactivate mode detection alongside existing edit mode checking for action=deactivate_job and job_id parameter. When in deactivate mode, render deactivation form section similar to edit section structure with heading "Stellenangebot deaktivieren", back link to dashboard, and form shortcode with id_param={job_id}. In job listings table, add "Deaktivieren" button in Actions column only for published jobs (status === 'publish'). Deactivate button uses warning/destructive color (red background) to differentiate from edit/view buttons. Follow same conditional rendering pattern as edit mode showing deactivation form OR listings, not both.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add create_job_deactivation_form() method following established pattern from create_job_edit_form(). Form includes deactivation_reason textarea (required, German label) and hidden job_id field. Configure Update Post action to set post_status='draft' removing job from public view. Map deactivation_reason to ACF meta field 'job_deactivation_reason'. Add ownership validation hook validate_job_deactivation_ownership() following same pattern as validate_job_ownership() to prevent URL tampering. Submit button: "Stellenangebot deaktivieren". Success message: "Ihr Stellenangebot wurde deaktiviert." Redirect to /anbieter-dashboard/. Add get_job_deactivation_form_id() helper following established pattern.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Phase 04: Job Deactivation System
- 2 plans created
- 3 total tasks defined
- Ready for execution
Plan 04-01: Deactivation form with reason capture (2 tasks)
Plan 04-02: Admin notification on deactivation (1 task)
Add admin UI class to main plugin bootstrap and initialize hooks in admin context only:
- Require class-admin-ui.php in main plugin file
- Initialize Admin_UI::setup_hooks() only when is_admin() is true
- Performance optimization: admin hooks don't load on frontend
Admin moderation interface now provides efficient job listing with custom columns and status filters.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Create DDHH_JM_Admin_UI class with custom columns for job_offer admin listing:
- Anbieter (provider org name + contact person from user meta)
- Standort (location from ACF field)
- Art (job type from ACF field)
- Eingereicht am (submission date)
Removed default author/date columns to reduce clutter. Made columns sortable for efficient moderation workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Document job edit form implementation with ownership validation
- Track security implementation preventing URL tampering
- Record conditional template rendering pattern
- List modified files and technical decisions
- Mark plan complete, ready for 03-03 or 03-04
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Summary documents email notification system implementation
- Admin receives German email on new job submission
- Email includes job details and direct edit link
- Smart triggering prevents spam on updates
- All tasks completed, no deviations
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>