Architectuur
Overzicht
Section titled “Overzicht”Het Werkbon thema is een traditioneel WordPress thema (geen block theme) met procedurele PHP, SCSS voor styling, en jQuery-gebaseerd JavaScript. Er zijn geen namespaces, geen classes, en geen autoloader — alle functionaliteit wordt geladen via een glob-include in functions.php.
Directory Structuur
Section titled “Directory Structuur”werkbon/├── functions.php # Glob loader (9 regels)├── header.php # HTML head, nav partial├── footer.php # wp_footer, closing tags├── index.php # Default template├── 404.php # Error pagina├── page-dashboard.php # Template: Dashboard├── page-jobs.php # Template: Jobs (meldingen lijst)├── page-jobs-form.php # Template: Jobs form (create/edit)├── page-login.php # Template: Login├── page-reports.php # Template: Reports├── style.css # Gecompileerde CSS (87KB)├── main-min.js # Gebundelde JS (87KB, NIET geminificeerd)├── package.json # Node dependencies│├── functions/ # 34 PHP bestanden│ ├── admin.php # Admin configuratie, menu's, login logo│ ├── login.php # Auth redirects, cookie expiration│ ├── roles.php # Role management (2 rollen)│ ├── scripts.php # Script/style enqueue│ ├── posttypes.php # CPT registratie (file, job, contact)│ ├── api-job.php # REST: POST /jobs/create (20.6KB)│ ├── api-contact.php # REST: GET/POST /contacts (23.9KB)│ ├── api-file.php # REST: GET /files + webhook (12.8KB)│ ├── form-addresses.php # AJAX address chain (37.9KB)│ ├── form-prefill.php # Form prefill logic (35.7KB)│ ├── form-work.php # Werkzaamheden modal+tabel (30.3KB)│ ├── form-material.php # Materiaal tabel (14.2KB)│ ├── form-search-contact.php # Contact zoek modal│ ├── form-overview.php # Overview paneel│ ├── wpforms.php # Core WPForms hooks│ ├── wpforms-field-mappings.php # Field ID ↔ ACF key mapping (18.7KB)│ ├── wpforms-add-or-update-contact.php # Contact upsert (12.6KB)│ ├── wpforms-create-file-post.php # Form 40 → FILE CPT│ ├── wpforms-update-job-post-submission.php # Form 3493 → JOB CPT│ ├── wpforms-edit-job.php # Edit mode detectie│ ├── wpforms-confirmation-overview.php # Smart tags│ ├── wpforms-normalize-phone.php # Telefoon E.164│ ├── wpforms-custom-date-field.php # Flatpickr integratie│ ├── wpforms-custom-select-field.php # Select2 integratie│ ├── wpforms-drag-and-drop.php # jQuery UI sortable│ ├── change-job-status-on-file-complete.php # Auto status update│ ├── update-employers-after-submit.php # Employer array parsing│ ├── add-prefill-body-class.php # Body class voor prefill│ ├── author.php # User/employer helpers│ ├── db-addresses.php # Address tabel management (15.6KB)│ ├── db-optimize.php # Postmeta indexes (8.8KB)│ ├── contact-admin-columns.php # Admin kolommen│ ├── modal-jobs.php # Melding modal + AJAX (9.2KB)│ └── modal-reports.php # Reports modal (3.5KB)│├── partials/ # 5 template partials│ ├── navigation.php # Navigatie + user dropdown (95 regels)│ ├── show-login.php # Login weergave (16 regels)│ ├── show-dashboard.php # Dashboard content (58 regels)│ ├── show-jobs.php # Meldingen lijst + filters (583 regels)│ └── show-reports.php # Rapporten lijst + filters (748 regels)│├── acf-json/ # 4 ACF field groups (JSON sync)│ ├── group_5c7027cd8e1d8.json # Werkbonnen velden│ ├── group_5e14d7eb790f3.json # Gebruiker velden│ ├── group_693b783dd764b.json # Meldingen velden│ └── group_694e8176243b2.json # Contact velden│├── assets/│ ├── fonts/ # Ginto Nord + Mercury (WOFF2/WOFF/OTF)│ ├── img/ # logo-tina.svg, logo-login.png, favicon│ ├── csv/ # Maasdelta adresbestanden│ ├── js/│ │ ├── main.js # CodeKit bundle manifest│ │ ├── nav.js # Navigatie (2.4KB)│ │ ├── modal-search-contact.js # Contact zoek modal (29.8KB)│ │ ├── file-conditional-logic.js # Conditional fields (2.2KB)│ │ └── modules/│ │ ├── prefill-manager.js # MutationObserver utilities│ │ ├── wpforms-werkbon.js # Form sync, type detectie│ │ ├── melding-modal.js # Modal AJAX (26.8KB)│ │ ├── form-field-locks.js # Field locking (14.4KB)│ │ ├── file-overview-sync.js # Overview panel (8.1KB)│ │ ├── form-prefill-helpers.js # Prefill utilities (5.9KB)│ │ └── submit-validation.js # Verify checkbox (8.3KB)│ └── scss/│ ├── style.scss # Entry point│ ├── variables.scss # Kleuren, breakpoints, mixins│ ├── elements.scss # Base elements│ ├── nav.scss # Navigatie│ ├── form-new.scss # Formulier styling (16.4KB)│ ├── form-work.scss # Werkzaamheden styling│ └── components/ # 18 SCSS partials│ ├── _wpforms-base.scss│ ├── _wpforms-verify.scss│ ├── _wpforms-streetname.scss│ ├── _wpforms-team.scss│ ├── _wpforms-material.scss│ ├── _meldingen.scss│ ├── _meldingen-filters.scss│ ├── _meldingen-pagination.scss│ ├── _cards.scss│ ├── _sections.scss│ ├── _pages.scss│ ├── _misc.scss│ ├── _modal.scss│ ├── _status.scss│ ├── _tooltip.scss│ └── _select2.scss│└── node_modules/ # jQuery, Flatpickr, Select2, ResetFunctions Loader
Section titled “Functions Loader”// functions.php — 9 regelsadd_action('init', function () { error_log('LOADED FUNCTIONS: ' . __FILE__); // DEBUG — verwijderen!});
foreach (glob(__DIR__ . '/functions/*') as $filename): require_once($filename);endforeach;Aandachtspunten:
- Laadvolgorde is onvoorspelbaar — afhankelijk van het bestandssysteem
- Elk bestand in /functions/ wordt automatisch geladen — ook niet-PHP bestanden of test/temp bestanden
- Geen namespace of class-based structuur — alle functies in global scope
- Debug logging actief —
error_log()bij elke pageload
Template Hierarchie
Section titled “Template Hierarchie”Browser Request ↓WordPress Template Resolution ↓page-{slug}.php (page-jobs.php, page-dashboard.php, etc.) ├── get_header() │ ├── HTML head, meta, favicon │ ├── wp_head() → CSS + JS enqueue │ └── get_template_part('partials/navigation') ├── get_template_part('partials/show-{naam}') │ └── show-jobs.php / show-dashboard.php / etc. └── get_footer() ├── wp_footer() → modals, inline scripts └── Closing tagsNiet aanwezige templates (niet nodig — CPTs zijn niet publiek queryable):
single.php,archive.php,search.php,category.php
Function Prefix Mix
Section titled “Function Prefix Mix”| Prefix | Herkomst | Voorbeelden |
|---|---|---|
acs_ | Legacy “ACS” project naam | acs_job_api_create, acs_contacts_list, acs_get_employers_all_index |
beam_ | Nieuwere conventie | beam_delete_job, beam_user_can_delete_jobs, beam_get_form40_field_map |
werkbon_ | Theme-specifiek | werkbon_enqueue_scripts, werkbon_addresses_lookup, werkbon_create_meta_index |
myproject_ | Legacy adres systeem | myproject_ajax_address |
hra_ | Contact upsert | hra_upsert_contact_from_wpforms, hra_set_relationship_field, hra_norm_email |
thra_ | Werkzaamheden form | thra_add_werkzaamheden_modal, thra_add_werkzaamheden_button |
my_ | Telefoon normalisatie | my_normalize_phone_nl_to_e164, my_get_area_code_by_city |
wpf_dev_ | WPForms dev hooks | wpf_dev_filter_placeholder_values, wpf_dev_process_filter_choices_values |
Build Tooling
Section titled “Build Tooling”CodeKit 3
Section titled “CodeKit 3”Config: config.codekit3 (84KB configuratiebestand)
SCSS pipeline:
- Entry:
assets/scss/style.scss - Imports: variables, elements, nav, form-new, form-work + 18 component partials
- Output:
style.css(87KB, niet geminificeerd)
JS bundeling via @codekit-prepend directives in main.js:
// @codekit-prepend "nav.js"// @codekit-prepend "modules/prefill-manager.js"// @codekit-prepend "modules/wpforms-werkbon.js"// @codekit-prepend "modules/melding-modal.js"// @codekit-prepend "modules/form-field-locks.js"// @codekit-prepend "modules/file-overview-sync.js"// @codekit-prepend "modules/form-prefill-helpers.js"// @codekit-prepend "modules/submit-validation.js"Output: main-min.js (87KB — NIET daadwerkelijk geminificeerd ondanks de naam)
Losse scripts (niet in bundle):
modal-search-contact.js(29.8KB) — apart geladen via wp_enqueue_scriptsfile-conditional-logic.js(2.2KB)
Script Loading
Section titled “Script Loading”wp_deregister_script('jquery');wp_register_script('jquery', get_template_directory_uri() . '/node_modules/jquery/dist/jquery.min.js', [], '3.7.1', false);// false = HEADER loading (niet footer) — vereist voor WPForms compatibiliteit
wp_enqueue_script('werkbon-main', get_template_directory_uri() . '/main-min.js', ['jquery'], $version, true);// defer attribuut toegevoegd via filterjQuery wordt in de header geladen (render-blocking) vanwege WPForms compatibiliteit.
JS Module-interactie
Section titled “JS Module-interactie”8 modules communiceren via 12+ globale variabelen. Dit is het meest fragiele deel van de applicatie.
Globale Variabelen
Section titled “Globale Variabelen”| Variabele | Gezet door | Gelezen door | Doel |
|---|---|---|---|
BEAM_FIELD_IDS | PHP (wp_localize_script) | Alle modules | Centrale field ID mapping |
BEAM_WPF40_CONFIG | PHP (wp_localize_script) | wpforms-werkbon | Form 40 configuratie |
BEAM_CONTACT_PREFILL_BUSY | modal-search-contact | form-field-locks | Pauzeert lock cycle tijdens prefill |
BEAM_ADDR_DISPLAY_MODE[formId] | modal-search-contact | form-field-locks | Adres in readonly display |
BEAM_ADDR_LOCK[formId] | modal-search-contact | form-addresses (PHP inline) | Voorkomt resets tijdens resolution |
BEAM_ADDR_INIT_SELECT2[formId] | PHP (form-addresses) | form-field-locks, modal-search | Lazy Select2 init callback |
BEAM_ADDR_PREFILL[formId] | modal-search-contact | form-addresses | Opgeslagen resolved address |
BEAM_ADDR_UNLOCKED[formId] | modal-search-contact | form-field-locks | Adres ontgrendeld |
BEAM_WPF40_UNLOCKED | form-field-locks | form-field-locks | Form 40 unlock state |
BEAM_WPF3493_UNLOCKED | form-field-locks | form-field-locks | Form 3493 unlock state |
BEAM_CREATE_CONTACT_SUMMARY[formId] | PHP | modal-search-contact | Summary render callback |
BEAM_CONTACT_LAYOUT[formId] | PHP | modal-search-contact | Field layout configuratie |
MYPROJECT_ADDR_READY[formId] | form-addresses | modal-search-contact | Address script ready flag |
PrefillManager | prefill-manager | Alle modules | Utility object |
Timing & Synchronisatie
Section titled “Timing & Synchronisatie”| Mechanisme | Interval | Module | Doel |
|---|---|---|---|
| Lock cycle polling | 250ms | form-field-locks | Check of velden vergrendeld moeten zijn |
| Overview sync polling | 300ms | file-overview-sync | Vang programmatische value changes |
| Address resolution lock | 350-700ms | modal-search-contact | Voorkom interferentie tijdens CSV lookup |
| Contact prefill busy | ~300ms | modal-search-contact | Pauzeer lock cycle tijdens velden vullen |
| Select2 AJAX debounce | 200ms | form-addresses | Voorkom overmatige API calls |
| MutationObserver | Event-based | form-field-locks, prefill-manager | Detecteer dynamische DOM wijzigingen |
CSS Architectuur
Section titled “CSS Architectuur”| Font | Gewichten | Formaten | Gebruik |
|---|---|---|---|
| Ginto Nord | 500 (Medium), 700 (Bold), 800 (Black) | WOFF2, WOFF, OTF | Headings, UI elementen |
| Mercury | 300 (Light), 400 (Regular), 500 (Medium), 700 (Bold) | WOFF2, WOFF, OTF | Body tekst |
Variabelen
Section titled “Variabelen”// CSS Custom Properties--ui-btn-primary: #...;--ui-btn-secondary: #...;--color-*: ...;
// SCSS Variables (variables.scss)$breakpoint-tablet: 768px; // Enige breakpoint$font-heading: 'Ginto Nord', sans-serif;$font-body: 'Mercury', serif;Responsive Design
Section titled “Responsive Design”- Een breakpoint: 768px
- Niet mobile-first — desktop stijlen als basis, media query voor mobile
- Component-specifieke responsive regels in SCSS partials
SCSS Components
Section titled “SCSS Components”| Component | Doel |
|---|---|
| _wpforms-base | WPForms basis styling |
| _wpforms-verify | Verify checkbox styling |
| _wpforms-streetname | Straatnaam veld styling |
| _wpforms-team | Team/monteur selectie |
| _wpforms-material | Materiaal tabel |
| _meldingen | Meldingen lijst |
| _meldingen-filters | Filter knoppen |
| _meldingen-pagination | Paginatie |
| _cards | Card componenten |
| _sections | Pagina secties |
| _pages | Pagina-specifieke stijlen |
| _misc | Overige stijlen |
| _modal | Modal dialogen |
| _status | Status indicators |
| _tooltip | Tooltips |
| _select2 | Select2 overrides |
Dependencies
Section titled “Dependencies”| Package | Versie | Doel | Geladen |
|---|---|---|---|
| jQuery | 3.7.1 | DOM manipulatie, AJAX, Select2/Flatpickr basis | Header (blocking) |
| Flatpickr | 4.6.13 | Datum picker in formulieren | Via WPForms |
| Select2 | 4.1.0-rc.0 | Enhanced select dropdowns (adres, contact) | Via form-addresses |
| Eric Meyer Reset | 2.0.0 | CSS reset | In SCSS import |
Alle packages worden geïnstalleerd via npm install en geladen vanuit node_modules/.
Performance Optimalisaties
Section titled “Performance Optimalisaties”Database
Section titled “Database”| Optimalisatie | Implementatie | Bestand |
|---|---|---|
| Postmeta indexes | 6 composite indexes op contact meta keys | db-optimize.php |
| Custom address tabel | Geïndexeerde lookups i.p.v. CSV scanning | db-addresses.php |
| Bulk meta cache | update_postmeta_cache() voorkomt N+1 queries | show-jobs.php, show-reports.php, contact-admin-columns.php |
Caching
Section titled “Caching”| Optimalisatie | TTL | Bestand |
|---|---|---|
| Employer user index | 12 uur (transient) | author.php |
| Webhook debounce | 3 seconden (transient) | api-contact.php |
| Contact upsert cache | Request-scoped (static) | wpforms-add-or-update-contact.php |
Query Optimalisatie
Section titled “Query Optimalisatie”- Direct array iteration:
foreach ($posts as $post)i.p.v.while (have_posts())+the_post() - Meta-aware ordering:
orderby => ['meta_value_num' => 'DESC', 'date' => 'DESC'] - Whitelisted per_page: Alleen 25, 50, 100 toegestaan (voorkomt misbruik)