docs(02): create phase 2 plans

Phase 02: Provider Registration & Auth
- 4 plans created
- 8 total tasks defined
- Ready for execution

Plans:
- 02-01: Formidable registration form with auto-login
- 02-02: Combined login/registration page
- 02-03: Provider dashboard template
- 02-04: Access control and redirects
This commit is contained in:
2026-01-14 19:12:07 +09:00
parent fecb654b82
commit 054adb721a
4 changed files with 564 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
---
phase: 02-provider-registration-auth
plan: 01
type: execute
depends_on: []
files_modified: [includes/class-formidable.php]
---
<objective>
Create Formidable Forms registration form with auto-login and provider role assignment.
Purpose: Enable external organizations to self-register as providers without admin intervention.
Output: Working registration form (F1) that creates WordPress users with ddhh_provider role and logs them in automatically.
</objective>
<execution_context>
~/.claude/get-shit-done/workflows/execute-plan.md
./summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-foundation-setup/01-03-SUMMARY.md
**From Phase 1:**
- Provider role `ddhh_provider` exists with capabilities: read, edit_job_offers, delete_job_offers, upload_files
- Role explicitly denies: publish_job_offers, edit_others_job_offers, edit_posts, edit_pages
- German UI required (v1)
**Tech stack:** Formidable Forms Pro with Registration Add-on available
</context>
<tasks>
<task type="auto">
<name>Task 1: Create Formidable registration form</name>
<files>N/A (Formidable forms stored in WP database)</files>
<action>
Create Formidable form via WordPress admin:
- Form name: "Provider Registration" (Anbieter-Registrierung)
- Fields (all required):
1. organization_name (text) - Label: "Organisationsname"
2. contact_person (text) - Label: "Ansprechperson"
3. email (email) - Label: "E-Mail"
4. password (password) - Label: "Passwort"
5. password_confirm (password) - Label: "Passwort bestätigen"
- German field labels per PROJECT.md
- Email field: unique validation (WordPress user_email must be unique)
- Password fields: min 8 characters, must match
Create helper class `includes/class-formidable.php` with static method get_registration_form_id() that returns the form ID (for use in shortcodes).
DO NOT use Formidable's default English labels - all labels must be German.
</action>
<verify>Form appears in Formidable Forms list, fields have German labels, email validation set to unique</verify>
<done>Registration form created with 5 fields, all required, German labels, email uniqueness enforced</done>
</task>
<task type="auto">
<name>Task 2: Configure auto-login and role assignment</name>
<files>includes/class-formidable.php</files>
<action>
In class-formidable.php, create static method setup_registration_hooks():
Hook into Formidable's `frm_after_create_entry` action:
- Check if form_id matches registration form
- Extract email and password from entry
- Create WordPress user with wp_insert_user():
- user_login: email prefix (before @)
- user_email: email from form
- user_pass: password from form
- role: 'ddhh_provider' (from Phase 1)
- display_name: contact_person from form
- Store organization_name as user meta 'ddhh_org_name'
- Auto-login user with wp_set_auth_cookie($user_id, true)
- Prevent duplicate submissions: check if email exists before creating user
Hook this to 'init' action in main class.
DO NOT assign 'subscriber' role - only 'ddhh_provider' role from Phase 1.
DO NOT send WordPress default registration email - providers should be logged in immediately.
</action>
<verify>Create test user via form, check user appears in WP users with ddhh_provider role, auto-login occurs (user is logged in after submission)</verify>
<done>Form submission creates user with ddhh_provider role, auto-logs in user, stores org name as meta, no duplicate users created</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] Registration form exists in Formidable with German labels
- [ ] Email field enforces uniqueness
- [ ] Form submission creates WordPress user with ddhh_provider role
- [ ] User is automatically logged in after registration
- [ ] Organization name stored as user meta
- [ ] No duplicate users created on re-submission
</verification>
<success_criteria>
- All tasks completed
- Form functional and creates users
- Auto-login works
- Role assignment correct (ddhh_provider)
- Ready for 02-02 (registration page integration)
</success_criteria>
<output>
After completion, create `.planning/phases/02-provider-registration-auth/02-01-SUMMARY.md`:
# Phase 2 Plan 1: Provider Registration Form Summary
**Formidable registration form with auto-login and provider role assignment**
## Accomplishments
- Registration form with 5 fields (German labels)
- Email uniqueness validation
- Auto-login after successful registration
- ddhh_provider role assignment
- Organization name storage in user meta
## Files Created/Modified
- Form created in WordPress database (Formidable)
- `includes/class-formidable.php` - Registration hooks and user creation
## Decisions Made
[Document any implementation choices or deviations]
## Issues Encountered
[Problems and resolutions, or "None"]
## Next Step
Ready for 02-02-PLAN.md (can run in parallel with 02-03)
</output>

View File

@@ -0,0 +1,141 @@
---
phase: 02-provider-registration-auth
plan: 02
type: execute
depends_on: ["02-01"]
files_modified: [includes/class-pages.php]
---
<objective>
Create combined login/registration page with Formidable shortcodes.
Purpose: Provide single entry point for providers to register or log in.
Output: WordPress page with registration form and login form in tabbed or stacked view.
</objective>
<execution_context>
~/.claude/get-shit-done/workflows/execute-plan.md
./summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/02-provider-registration-auth/02-01-SUMMARY.md
**From 02-01:**
- Registration form exists with ID accessible via DDHH_JM_Formidable::get_registration_form_id()
- Form creates users with ddhh_provider role and auto-logs in
**Requirements:**
- German UI (v1)
- Combined login/registration view
- Match existing Elementor site style
</context>
<tasks>
<task type="auto">
<name>Task 1: Create login/registration page</name>
<files>includes/class-pages.php</files>
<action>
Create `includes/class-pages.php` with static method create_provider_pages():
Use wp_insert_post() to create page "Anbieter Login":
- post_title: 'Anbieter Login'
- post_name: 'anbieter-login'
- post_status: 'publish'
- post_type: 'page'
- post_content: Two-section layout with:
1. Registration section with heading "Neu registrieren" and Formidable shortcode [formidable id={registration_form_id}]
2. Login section with heading "Bereits registriert?" and WordPress default login form wp_login_form()
Store page ID in option 'ddhh_jm_login_page_id' for later reference.
Hook create_provider_pages() to plugin activation (call in Activator class).
Check if page already exists (by post_name) before creating to avoid duplicates on re-activation.
DO NOT create separate pages for login vs registration - combine in one page per PROJECT.md.
</action>
<verify>Page "Anbieter Login" exists at /anbieter-login/, displays registration form and login form</verify>
<done>Page created, accessible, shows both registration and login forms, German headings</done>
</task>
<task type="auto">
<name>Task 2: Style combined view for consistency</name>
<files>includes/class-pages.php</files>
<action>
Add basic styling to make login/registration sections visually distinct:
In post_content, wrap sections in div.ddhh-auth-container with:
- Registration section: div.ddhh-register-section
- Login section: div.ddhh-login-section
Add simple CSS (inline in page or via enqueued stylesheet):
- Two-column layout on desktop (50/50 split)
- Stacked on mobile
- Visual separator (border or background color difference)
- Headings styled consistently
Match Elementor site colors if possible (check if theme provides CSS variables).
DO NOT over-style - keep it minimal and functional for now. Phase 7 will polish UI.
</action>
<verify>Page displays cleanly on desktop (side-by-side) and mobile (stacked), forms readable and usable</verify>
<done>Combined view styled, responsive, visually clear separation between register and login sections</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] Page "Anbieter Login" exists and is published
- [ ] Registration form displays via shortcode
- [ ] Login form displays via wp_login_form()
- [ ] Layout responsive (desktop: side-by-side, mobile: stacked)
- [ ] German headings used
- [ ] Page accessible at /anbieter-login/
</verification>
<success_criteria>
- All tasks completed
- Combined login/registration page functional
- Both forms display and work
- Responsive layout
- Ready for Phase 3 (job submission forms)
</success_criteria>
<output>
After completion, create `.planning/phases/02-provider-registration-auth/02-02-SUMMARY.md`:
# Phase 2 Plan 2: Login/Registration Page Summary
**Combined login/registration page with responsive layout**
## Accomplishments
- WordPress page "Anbieter Login" created programmatically
- Registration form integrated via Formidable shortcode
- WordPress login form integrated
- Responsive two-column/stacked layout
- German headings
## Files Created/Modified
- `includes/class-pages.php` - Page creation and layout
- `includes/class-activator.php` - Hook create_provider_pages()
## Decisions Made
[Document layout choices, styling approach]
## Issues Encountered
[Problems and resolutions, or "None"]
## Next Step
Ready for 02-04-PLAN.md (sequential after 02-03 completes)
</output>

View File

@@ -0,0 +1,148 @@
---
phase: 02-provider-registration-auth
plan: 03
type: execute
depends_on: []
files_modified: [includes/class-dashboard.php, templates/provider-dashboard.php]
---
<objective>
Create provider dashboard template that lists user's own job_offer posts.
Purpose: Give providers a central view of their published job listings.
Output: Dashboard page accessible at /anbieter-dashboard/ showing provider's jobs with edit/view links.
</objective>
<execution_context>
~/.claude/get-shit-done/workflows/execute-plan.md
./summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/01-foundation-setup/01-02-SUMMARY.md
@.planning/phases/01-foundation-setup/01-03-SUMMARY.md
**From Phase 1:**
- Custom post type `job_offer` exists with custom capabilities
- Providers have edit_job_offers capability (own posts only)
- ACF fields available: job_location, job_type, job_deadline, job_contact_email, job_logo
**Requirements:**
- German UI
- List only current user's job_offer posts
- Show edit and view links
- Simple table layout
</context>
<tasks>
<task type="auto">
<name>Task 1: Create dashboard template</name>
<files>templates/provider-dashboard.php, includes/class-dashboard.php</files>
<action>
Create `templates/provider-dashboard.php`:
- Check if user is logged in and has ddhh_provider role (else show error message)
- Query current user's job_offer posts using WP_Query:
- post_type: 'job_offer'
- author: get_current_user_id()
- post_status: ['publish', 'pending', 'draft']
- orderby: 'date'
- order: 'DESC'
- Display results in HTML table with columns:
1. Title (job post title)
2. Status (Veröffentlicht / Ausstehend / Entwurf)
3. Location (ACF field job_location)
4. Type (ACF field job_type)
5. Actions (Bearbeiten link to edit screen, Ansehen link to public view if published)
- German labels for all headings
- If no jobs, show message "Sie haben noch keine Stellenangebote erstellt."
Create `includes/class-dashboard.php` with static method get_template():
- Returns path to templates/provider-dashboard.php
- Handles template loading with load_template()
DO NOT use wp-admin edit links - providers should not access WP-Admin. Use frontend edit approach or direct edit_post_link() which WordPress handles based on capabilities.
</action>
<verify>Template file exists, displays current user's jobs in table format, German labels present</verify>
<done>Dashboard template created, queries user's posts correctly, displays in table with German labels</done>
</task>
<task type="auto">
<name>Task 2: Create dashboard page and shortcode</name>
<files>includes/class-dashboard.php, includes/class-pages.php</files>
<action>
In class-pages.php create_provider_pages(), add second page creation:
- post_title: 'Anbieter Dashboard'
- post_name: 'anbieter-dashboard'
- post_content: [ddhh_provider_dashboard] shortcode
- Store page ID in option 'ddhh_jm_dashboard_page_id'
In class-dashboard.php, register shortcode 'ddhh_provider_dashboard':
- Shortcode handler loads templates/provider-dashboard.php
- Returns output buffered content
Check page doesn't already exist before creating.
Hook shortcode registration to 'init' action in main class.
</action>
<verify>Dashboard page exists at /anbieter-dashboard/, shortcode renders template, table displays user's jobs</verify>
<done>Dashboard page created, shortcode functional, displays job list for logged-in provider</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] Dashboard template queries only current user's job_offer posts
- [ ] Table displays with German column headings
- [ ] Edit and View links present for each job
- [ ] Status displayed in German (Veröffentlicht/Ausstehend/Entwurf)
- [ ] Empty state message shows when no jobs exist
- [ ] Page accessible at /anbieter-dashboard/
</verification>
<success_criteria>
- All tasks completed
- Dashboard functional for providers
- Queries scoped to current user
- German UI throughout
- Ready for 02-04 (access control)
</success_criteria>
<output>
After completion, create `.planning/phases/02-provider-registration-auth/02-03-SUMMARY.md`:
# Phase 2 Plan 3: Provider Dashboard Summary
**Dashboard template displaying provider's own job listings**
## Accomplishments
- Dashboard template with WP_Query for current user's jobs
- Table layout with German column headings
- Status display (Veröffentlicht/Ausstehend/Entwurf)
- Edit and View links for each job
- Shortcode integration
- Dashboard page created at /anbieter-dashboard/
## Files Created/Modified
- `templates/provider-dashboard.php` - Dashboard template
- `includes/class-dashboard.php` - Shortcode and template loader
- `includes/class-pages.php` - Added dashboard page creation
## Decisions Made
[Document query approach, template structure]
## Issues Encountered
[Problems and resolutions, or "None"]
## Next Step
Ready for 02-04-PLAN.md
</output>

View File

@@ -0,0 +1,134 @@
---
phase: 02-provider-registration-auth
plan: 04
type: execute
depends_on: ["02-03"]
files_modified: [includes/class-access-control.php]
---
<objective>
Implement access control and redirects for provider role.
Purpose: Prevent providers from accessing WP-Admin (except profile) and protect dashboard page.
Output: Access control hooks that enforce provider restrictions per PROJECT.md requirements.
</objective>
<execution_context>
~/.claude/get-shit-done/workflows/execute-plan.md
./summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/01-foundation-setup/01-03-SUMMARY.md
@.planning/phases/02-provider-registration-auth/02-03-SUMMARY.md
**From PROJECT.md:**
- Constraint: "Providers: restricted capabilities, no WP-Admin access except profile"
- Core value: Admin moderation is the trust layer
**From Phase 1:**
- Provider role `ddhh_provider` exists with no admin capabilities
**From 02-03:**
- Dashboard page exists at /anbieter-dashboard/
</context>
<tasks>
<task type="auto">
<name>Task 1: Redirect providers away from WP-Admin</name>
<files>includes/class-access-control.php</files>
<action>
Create `includes/class-access-control.php` with static method setup_hooks():
Hook into 'admin_init' action:
- Check if current user has role 'ddhh_provider' (use wp_get_current_user()->roles)
- If ddhh_provider AND not accessing profile.php or admin-ajax.php:
- Get dashboard page URL: get_permalink(get_option('ddhh_jm_dashboard_page_id'))
- Redirect using wp_redirect($dashboard_url) and exit
- Allow profile.php (providers can edit their profile)
- Allow admin-ajax.php (needed for AJAX requests from frontend)
Hook this to 'init' action in main class.
DO NOT block all admin access - allow profile.php so providers can change their password and email.
DO NOT redirect on AJAX requests (admin-ajax.php must remain accessible).
</action>
<verify>Provider user accessing wp-admin/ gets redirected to /anbieter-dashboard/, but wp-admin/profile.php remains accessible</verify>
<done>WP-Admin redirect implemented, profile access preserved, dashboard redirect functional</done>
</task>
<task type="auto">
<name>Task 2: Protect dashboard page (logged-in providers only)</name>
<files>includes/class-access-control.php</files>
<action>
In class-access-control.php, add static method protect_dashboard():
Hook into 'template_redirect' action:
- Check if current page is dashboard page (using get_option('ddhh_jm_dashboard_page_id'))
- If yes:
- Check if user is logged in: is_user_logged_in()
- Check if user has ddhh_provider role
- If NOT logged in OR NOT ddhh_provider: redirect to login page (get_option('ddhh_jm_login_page_id'))
This ensures only logged-in providers can access the dashboard.
DO NOT use wp_die() - use wp_redirect() to login page with a friendly redirect flow.
</action>
<verify>Non-logged-in users accessing /anbieter-dashboard/ get redirected to /anbieter-login/, logged-in providers see dashboard</verify>
<done>Dashboard protected, only providers can access, redirects to login page if unauthorized</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] Provider accessing wp-admin/ gets redirected to dashboard
- [ ] Provider CAN access wp-admin/profile.php
- [ ] Non-logged-in users accessing dashboard get redirected to login
- [ ] Logged-in providers CAN access dashboard
- [ ] Admin users are not affected by redirects
</verification>
<success_criteria>
- All tasks completed
- Provider role properly restricted from WP-Admin
- Dashboard protected and accessible only to providers
- Profile access preserved for providers
- Phase 2 complete - ready for Phase 3 (job submission forms)
</success_criteria>
<output>
After completion, create `.planning/phases/02-provider-registration-auth/02-04-SUMMARY.md`:
# Phase 2 Plan 4: Access Control & Redirects Summary
**Access control enforcing provider restrictions and dashboard protection**
## Accomplishments
- WP-Admin redirect for providers (except profile.php)
- Dashboard page protection (logged-in providers only)
- Login redirect for unauthorized dashboard access
- Profile access preserved for providers
## Files Created/Modified
- `includes/class-access-control.php` - Redirect hooks and protection logic
- `includes/class-ddhh-job-manager.php` - Hook access control setup
## Decisions Made
[Document redirect approach, exceptions made]
## Issues Encountered
[Problems and resolutions, or "None"]
## Next Step
Phase 2 complete. Ready for Phase 3 (Job Management Core).
</output>