chore: ARCHITECTURE.md

This commit is contained in:
2025-09-25 13:55:12 -04:00
parent dfa2cec646
commit 4ac9ceb50e
3 changed files with 348 additions and 5 deletions

343
.claude/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,343 @@
# ARCHITECTURE.md - CCAT Data Structure Reference
## Table of Contents
- [Custom Post Types Overview](#custom-post-types-overview)
- [Taxonomies Overview](#taxonomies-overview)
- [Custom Post Type Fields](#custom-post-type-fields)
- [Abstract Field Groups](#abstract-field-groups)
- [Field Relationships](#field-relationships)
- [Technical Implementation](#technical-implementation)
---
## Custom Post Types Overview
| CPT Name | Label | GraphQL Single | Rewrite Slug | Hierarchical | Description |
|----------|--------|----------------|--------------|--------------|-------------|
| `contributor` | Contributor | `Contributor` | -- | No | Artist/organization profiles |
| `event` | Event | `Event` | `evenement` | Yes | Base event descriptions without specific dates |
| `listing` | Listing | `Listing` | `offre` | No | Job offers and opportunities |
| `location` | Location | `Location` | `lieu` | Yes | Venue information with hierarchical structure |
| `page` | Page | `Page` | `page` | Yes | WordPress default pages with flexible content |
| `profile` | Profile | `Profile` | `profil` | No | User cultural profiles for members |
| `project` | Project | `Project` | `projet` | No | CCAT projects and initiatives |
| `representation` | Representation | `Representation` | -- | No | Specific event instances with dates/times/locations |
| `resource` | Resource | `Resource` | `ressource` | No | Document/link repository |
| `template` | Template | `Template` | -- | No | Reusable content blocks for flexible layouts |
---
## Taxonomies Overview
| Taxonomy Name | Label | Associated CPTs | Hierarchical | GraphQL Single | Description |
|---------------|--------|----------------|--------------|----------------|-------------|
| `discipline` | Discipline | `contributor`, `event` | Yes | `Discipline` | Artistic/cultural categories |
| `listing-category` | Listing Category | `listing` | Yes | `ListingCategory` | Job/proposal types |
| `project-category` | Project Category | `project` | Yes | `ProjectCategory` | CCAT project types |
| `resource-category` | Resource Category | `resource` | Yes | `ResourceCategory` | Resource organization categories |
---
## Custom Post Type Fields
### Contributor (`group_post_contributor`)
**Purpose:** Artist/organization profiles that can be linked to events
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `contributor_type` | Contributor type | select | Yes | Type of contributor (individual, organisation) |
| `alternative_titles` | Alternative titles | repeater | No | Alternative names for the contributor |
| `alternative_titles.name` | Name | text | Yes | Alternative name entry |
| `description` | Description | wysiwyg | No | Rich text description of contributor |
| `localities` | Localities | repeater | No | Physical locations associated with contributor |
| `localities.address` | Address | clone | Yes | Clones city address field for location |
| `disciplines` | Discipline(s) | taxonomy | No | Links to discipline taxonomy terms |
| `entity` | Entity | clone | No | External identifiers |
| `gallery` | Gallery | clone | No | Media gallery |
| `social` | Social | clone | No | Social media profiles |
### Event (`group_post_event`)
**Purpose:** Base event information without specific dates/times
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `event_type` | Event type | select | Yes | Type of event (Exposition, Festival, Spectacle) |
| `target_audience` | Target audience | select | Yes | Age group (Tout public, Enfants, Familial, Adultes 18+) |
| `description` | Description | wysiwyg | No | Rich text event description |
| `disciplines` | Discipline(s) | taxonomy | No | Links to discipline taxonomy terms |
| `is_wordless` | Wordless | true_false | No | Indicates if event is wordless |
| `languages` | Language(s) | acfe_languages | No | Event languages (conditional: shown if not wordless) |
| `entity` | Entity | clone | No | Clones abstract entity group (external identifiers) |
| `social` | Social | clone | No | Clones abstract social group (social media profiles) |
| `gallery` | Gallery | clone | No | Clones abstract gallery group (images/videos) |
| `credits` | Credits | clone | No | Clones abstract credits group (contributors and roles) |
### Listing (`group_post_listing`)
**Purpose:** Job offers and opportunities
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `listing_category` | Listing category | taxonomy | Yes | Links to listing_category taxonomy |
| `deadline` | Application deadline | date_picker | No | Application deadline date |
| `external_link` | External link | url | No | Link to external application |
### Location (`group_post_location`)
**Purpose:** Venue information for events
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `location_type` | Location type | select | Yes | Type of location (virtual, Bar, Salle de spectacle) |
| `description` | Description | wysiwyg | No | Rich text description of location |
| `address` | Address | clone | No | Clones geo address field (conditional: not shown for virtual) |
| `configurations` | Possible configurations | repeater | No | Different setup configurations for venue |
| `configurations.name` | Configuration name | text | Yes | Name of the configuration |
| `universal_access` | Universal access | checkbox | No | Accessibility features available |
| `entity` | Entity | clone | No | External identifiers |
| `social` | Social | clone | No | Social media profiles |
| `gallery` | Gallery | clone | No | Media gallery |
### Page (`group_post_page`)
**Purpose:** WordPress default pages with flexible content capabilities
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `builder` | Builder | clone | No | Clones abstract builder group (flexible content sections) |
**Note:** This field group extends WordPress's default `page` post type with flexible content capabilities. The default content editor is hidden (`hide_on_screen: the_content`) in favor of the flexible builder system.
### Profile (`group_post_profile`)
**Purpose:** User profile information for members
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `contact` | Contact | clone | Yes | Clones abstract contact group (personal info & address) |
| `billing_same` | Same as contact | true_false | No | Whether billing matches contact info |
| `billing` | Billing | clone | No | Separate billing contact info (conditional: shown if billing_same is false) |
| `profile_type` | Profile type | select | Yes | Type of profile (individual, collective, organization, institution) |
| `email_preferences` | Email preferences | group | No | Group containing email subscription preferences |
| `email_preferences.categories` | Categories | checkbox | No | Email categories to subscribe to |
| `email_preferences.disciplines` | Disciplines | checkbox | No | Discipline-based email preferences |
| `email_preferences.event_types` | Event types | checkbox | No | Event type email preferences |
| `email_preferences.mrc` | MRC | checkbox | No | Regional email preferences |
### Project (`group_post_project`)
**Purpose:** CCAT projects and initiatives
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `project_categories` | Project categories | taxonomy | Yes | Links to project_category taxonomy |
| `period` | Period | group | No | Project timeline |
| `period.start_month` | Start month | date_picker | Yes | Project start (month/year format) |
| `period.end_month` | End month | date_picker | No | Project end (month/year format) |
| `builder` | Builder | clone | No | Clones abstract builder group (flexible content sections) |
### Representation (`group_post_representation`)
**Purpose:** Specific event instances with dates/times
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `event` | Event | post_object | Yes | Links to base Event post |
| `description` | Description | wysiwyg | No | Specific description for this representation |
| `schedule_type` | Schedule type | select | Yes | Type of scheduling (range, days, multiple) |
| `range` | Range | group | No | Date range fields (conditional: when schedule_type = range) |
| `range.start_date` | Start date | date_picker | Yes | Range start date |
| `range.end_date` | End date | date_picker | Yes | Range end date |
| `days` | Days | repeater | No | Individual days (conditional: when schedule_type = days/multiple) |
| `days.start_date_time` | Start date/time | date_time_picker | Yes | Event start with time |
| `days.end_time` | End time | time_picker | No | Event end time |
| `offer` | Offer | clone | No | Clones abstract offer group (pricing, location, registration) |
### Resource (`group_post_resource`)
**Purpose:** Document repository
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `resource_category` | Resource category | taxonomy | Yes | Links to resource_category taxonomy |
| `documents` | Documents | repeater | No | List of documents |
| `documents.title` | Title | text | Yes | Document title |
| `documents.document_type` | Document type | select | Yes | Type of document (file, url) |
| `documents.file` | File | file | Yes | File upload (conditional: when document_type = file) |
| `documents.url` | URL | url | Yes | External URL (conditional: when document_type = url) |
### Template (`group_post_template`)
**Purpose:** Reusable content templates
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `builder` | Builder | clone | No | Clones abstract builder group (flexible content sections) |
---
## Abstract Field Groups
### Address City (`group_abstract_address_city`)
**Purpose:** City-level address information
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `address` | Address | acfe_address | Yes | Address with city-level search, Canada only |
### Address Contact (`group_abstract_address_contact`)
**Purpose:** Full contact address information
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `address` | Address | acfe_address | Yes | Complete address with street details, Canada only |
### Address Geo (`group_abstract_address_geo`)
**Purpose:** Geographic address with coordinates
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `address` | Address | acfe_address | Yes | Address with establishment search and lat/lng coordinates |
### Builder (`group_abstract_builder`)
**Purpose:** Flexible content builder with layout sections
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `sections` | Sections | flexible_content | No | Flexible content with layouts: |
| `sections.text_block` | Text block | layout | - | WYSIWYG content block |
| `sections.text_block.content` | Content | wysiwyg | Yes | Rich text content |
| `sections.template` | Template | layout | - | Reference to template post |
| `sections.template.template` | Template | post_object | Yes | Links to Template post type |
### Contact (`group_abstract_contact`)
**Purpose:** Personal contact information
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `first_name` | First name | text | Yes | Contact's first name |
| `last_name` | Last name | text | Yes | Contact's last name |
| `email` | Email | email | Yes | Contact email address |
| `phone` | Phone | acfe_phone_number | Yes | Phone number (Canada format) |
| `address` | Address | clone | Yes | Clones contact address field |
### Credits (`group_abstract_credits`)
**Purpose:** Attribution and contributor roles
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `contributions` | Contributions | repeater | No | List of contributor roles |
| `contributions.contributionTypes` | Contribution types | checkbox | Yes | Types of contribution (Auteur, Compositeur, Interprète) |
| `contributions.contributor` | Contributor | post_object | Yes | Links to Contributor post |
### Entity (`group_abstract_entity`)
**Purpose:** External entity identifiers
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `identifiers` | Identifiers | repeater | No | External identifier URLs |
| `identifiers.uri` | URI | url | Yes | External identifier URL |
### Gallery (`group_abstract_gallery`)
**Purpose:** Media gallery with images and videos
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `medias` | Medias | repeater | No | List of media items |
| `medias.mediaType` | Media type | select | Yes | Type of media (image, youtube) |
| `medias.image` | Image | image | Yes | Image upload (conditional: when mediaType = image) |
| `medias.youtube_url` | YouTube URL | url | Yes | YouTube video URL (conditional: when mediaType = youtube) |
### Offer (`group_abstract_offer`)
**Purpose:** Event offering details (pricing, registration, location)
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `attendance_mode` | Attendance mode | select | Yes | How event is attended (offline, online, mixed) |
| `is_async` | Is asynchronous | true_false | No | Whether online event is asynchronous |
| `offer_status` | Offer status | select | Yes | Event status (upcoming, confirmed, complete, cancelled, postponed) |
| `where` | Where | group | No | Location details (conditional: for offline/mixed events) |
| `where.location` | Location | post_object | Yes | Links to Location post |
| `where.configuration` | Configuration | select | No | Venue configuration |
| `pricing` | Pricing | group | No | Price information |
| `pricing.is_free` | Free | true_false | No | Whether event is free |
| `pricing.min_price` | Minimum price | number | Yes | Minimum price (conditional: if not free) |
| `registration` | Registration | group | No | Registration details |
| `registration.form` | Form | select | No | Registration form |
| `registration.url` | URL | url | No | Registration URL |
| `registration.email` | Email | email | No | Registration email |
| `registration.phone` | Phone | acfe_phone_number | No | Registration phone |
| `notifications` | Notifications | repeater | No | Scheduled notifications |
| `notifications.date_time` | Date/time | date_time_picker | Yes | When to send notification |
| `notifications.subject` | Subject | text | Yes | Email subject |
| `notifications.message` | Message | wysiwyg | Yes | Email message content |
| `notifications.sent_status` | Sent status | select | Yes | Notification status (planned, sent, failed) |
### Social (`group_abstract_social`)
**Purpose:** Social media profiles
| Field Name | Label | Type | Required | Description |
|------------|-------|------|----------|-------------|
| `profiles` | Profiles | repeater | No | List of social media profiles |
| `profiles.url` | URL | url | Yes | Social media profile URL |
---
## Field Relationships
### Post Object Relationships
- **Event → Representation**: Base events are instantiated through representations
- **Representation → Event**: Each representation references one base event
- **Representation → Location**: Event instances specify venue through offer.where.location
- **Contributor → Credits**: Contributors are linked to events through credits system
- **Template → Builder**: Templates contain flexible content sections that can be referenced
### Taxonomy Relationships
- **Discipline**: Applied to both `event` and `contributor` CPTs
- **Resource Category**: Applied to `resource` CPTs only
- **Project Category**: Applied to `project` CPTs only
- **Listing Category**: Applied to `listing` CPTs only
### Clone Field Usage
| Abstract Group | Used By CPTs |
|----------------|--------------|
| Address City | Contributor (locality) |
| Address Contact | Profile (contact, billing) |
| Address Geo | Location (address) |
| Builder | Project, Template, Page |
| Contact | Profile (contact, billing) |
| Credits | Event |
| Entity | Event, Contributor, Location |
| Gallery | Event, Contributor, Location |
| Offer | Representation |
| Social | Event, Contributor, Location, Options Page |
---
## Technical Implementation
### GraphQL Integration
- All CPTs enabled for GraphQL with custom single/plural names
- All fields set `show_in_graphql: 1` for API exposure
- Required fields use `graphql_non_null: 1` for schema validation
- Custom GraphQL field names follow camelCase convention
### ACF Extended Pro Features
- **Advanced Address Fields**: Google Places integration, Canada-specific
- **Phone Number Fields**: Country-specific formatting (Canada)
- **Language Selection**: Multi-language support with conditional logic
- **Flexible Content**: Modal editing, preview capabilities
- **Template System**: Reusable content blocks with clone functionality
### Conditional Logic Patterns
- Address fields hidden for virtual locations (`location_type != 'virtual'`)
- Language fields hidden for wordless events (`is_wordless != 1`)
- Billing fields conditional on "same as contact" toggle
- Pricing fields conditional on free/paid status
- Schedule layouts vary based on schedule type selection
### WordPress Integration
- Custom rewrite slugs in French for public-facing URLs
- Hierarchical structure for events and locations
- Thumbnail and excerpt support for content display
- Page attributes for ordering and parent-child relationships
- Translation-ready with `__()` functions and 'ccat' text domain
### Performance Considerations
- Clone fields reduce field duplication and maintain consistency
- Taxonomy relationships indexed for efficient querying
- GraphQL schema optimized with proper field exposure
- Conditional field loading reduces unnecessary data transfer

View File

@@ -85,7 +85,7 @@ __( "Interprète", 'ccat' );
__( "Is asynchronous", 'ccat' );
__( "Language(s)", 'ccat' );
__( "Last name", 'ccat' );
__( "Locality", 'ccat' );
__( "Localities", 'ccat' );
__( "Location", 'ccat' );
__( "Location type", 'ccat' );
__( "MRC", 'ccat' );

View File

@@ -139,8 +139,8 @@
},
{
"key": "field_685aa158687d2",
"label": "Locality",
"name": "locality",
"label": "Localities",
"name": "localities",
"aria-label": "",
"type": "repeater",
"instructions": "",
@@ -160,7 +160,7 @@
"button_label": "Ajouter un élément",
"show_in_graphql": 1,
"graphql_description": "",
"graphql_field_name": "locality",
"graphql_field_name": "localities",
"graphql_non_null": 0,
"rows_per_page": 20,
"sub_fields": [
@@ -343,5 +343,5 @@
"graphql_types": "",
"acfe_meta": "",
"acfe_note": "",
"modified": 1758811648
"modified": 1758822397
}