From 8c4279f9bbe7ec4681412865b999f2f4457d80ac Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 10 Feb 2026 20:26:34 +0000
Subject: [PATCH] =legacy latest

---
 content/progress.php |  204 +++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 166 insertions(+), 38 deletions(-)

diff --git a/content/progress.php b/content/progress.php
index 7ba6d1a..38bbe49 100644
--- a/content/progress.php
+++ b/content/progress.php
@@ -1,6 +1,6 @@
 <?php
 // /content/progress.php
-use JVBase\meta\MetaManager;
+use JVBase\meta\Meta;
 
 function altr_progress():array
 {
@@ -14,6 +14,8 @@
         'hide_children' => true,
         'is_timeline'   => true,
         'show_feed'    => true,
+        'show_directory'=> true,
+        'directory_extra'=> ['goal', 'skin-type','age'],
         'hierarchical'  => true,
         'icon'         => 'arrows-left-right',
         'rewrite'      => [
@@ -25,26 +27,35 @@
                 'label' => 'Progression',
             ]
         ],
+        'custom_order' => [
+            'number'    => [
+                'label' => 'Number of Treatments',
+                'icon'  => 'hash-straight',
+                'for'   => 'progress',
+            ]
+        ],
         'seo' => [
             'schema' => [
                 'type' => 'BeforeAfter',
                 'name' => '{{post_title}}',
                 'description' => '{{post_excerpt}}',
-                'about' => ['@id' => '{{site_url}}/#laser-removal-service'],
                 'temporalCoverage' => '{{post_date}}/{{last_date}}',
                 'additionalProperty' => [
                     ['name' => 'Number of sessions', 'value' => '{{number.name}}'],
                     ['name' => 'Treatment area', 'value' => '{{body-part.name}}'],
+                    ['name' => 'Tattoo style', 'value' => '{{style.name}}'],
+                    ['name' => 'Skin type', 'value' => '{{skin-type.name}}'],
+                    ['name' => 'Goal', 'value' => '{{goal.name}}'],
                 ],
-                'associatedMedia' => '{{timeline_photos}}', // parent post thumbnail = before; each child post has a post thumbnail, too
+                'associatedMedia' => '{{timeline_photos}}',
             ],
             'meta' => [
-                'title' => '{{body-part.name}} Laser Tattoo Removal – Before & After',
-                'description' => 'Documented progress of {{body-part.name}} laser tattoo removal over {{number.name}} sessions.',
+                'title' => '{{style.name}} {{theme.name}} Tattoo – Before & After {{number}} Laser Removal Sessions',
+                'description' => 'See this {{style.name}} {{theme.name}} {{age.name}}-old tattoo before and after {{number}} laser tattoo removal treatments on the {{body-part.name}}.',
             ],
             'archive' => [
-                'type'  => 'CollectionPage',
-                'name'  => 'Tattoos Before and After Laser Tattoo Removal',
+                'type' => 'CollectionPage',
+                'name' => 'Tattoos Before and After Laser Tattoo Removal',
             ],
         ],
         'feed'      => [
@@ -79,7 +90,6 @@
                     'trash'     => 'Scrap',
                     'delete'    => 'Permanently Delete'
                 ],
-                'section'   => 'progression',
                 'for_all'   => true,
             ],
             'post_date'  => [
@@ -104,6 +114,15 @@
                 'section'   => 'progression',
                 'hint'      => 'Not public, just to make it easier to find'
             ],
+            'body-part' => [
+                'type'  => 'taxonomy',
+                'taxonomy'  => 'body-part',
+                'label' => 'Body Part',
+                'autocomplete' => true,
+                'quickEdit' => true,
+                'createNew' => true,
+                'section'   => 'progression'
+            ],
             'goal' => [
                 'type'  => 'taxonomy',
                 'taxonomy'  => 'goal',
@@ -122,15 +141,7 @@
                 'createNew' => true,
                 'section'   => 'progression',
                 'for_all'   => true,
-            ],
-            'body-part' => [
-                'type'  => 'taxonomy',
-                'taxonomy'  => 'body-part',
-                'label' => 'Body Part',
-                'autocomplete' => true,
-                'quickEdit' => true,
-                'createNew' => true,
-                'section'   => 'progression'
+                'hidden'    => true,
             ],
             'style' => [
                 'type'  => 'taxonomy',
@@ -141,6 +152,15 @@
                 'createNew' => true,
                 'section'   => 'progression'
             ],
+            'theme' => [
+                'type'  => 'taxonomy',
+                'taxonomy'  => 'theme',
+                'autocomplete' => true,
+                'label' => 'Tattoo Theme',
+                'quickEdit' => true,
+                'createNew' => true,
+                'section'   => 'progression'
+            ],
             'skin-type' => [
                 'type'  => 'taxonomy',
                 'taxonomy'  => 'skin-type',
@@ -160,13 +180,13 @@
                 'section'   => 'progression'
             ],
             'number' => [
-                'type'  => 'taxonomy',
-                'taxonomy'  => 'number',
-                'autocomplete'      => true,
+                'type'  => 'text',
+                'subtype'  => 'number',
                 'label' => 'Number of Treatments',
                 'quickEdit' => true,
-                'createNew' => true,
-                'section'   => 'progression'
+                'section'   => 'progression',
+                'for_all'   => true,
+                'hidden'    => true,    //auto calculated
             ],
             'post_content'   => [
                 'type'  => 'textarea',
@@ -174,6 +194,13 @@
                 'label' => 'Notes',
                 'section'   => 'progression',
                 'for_all'   => true,
+            ],
+            'last_date' => [
+                'type'  => 'number',
+                'label' => 'Last Date',
+                'hidden'    => true,
+                'default'   => 0,
+                'for_all'   => true,
             ]
         ],
         'upload_title' => 'Upload Before & Afters',
@@ -182,30 +209,41 @@
 
 add_filter('jvbFeedItem', 'altr_progress_item', 10, 2);
 
-function altr_progress_item(string $out, array $config):string
+function altr_progress_item(string $out, string $content):string
 {
-    if (!in_array('progress', $config['content'])) {
+    if ($content !== 'progress') {
         return $out;
     }
 
     ob_start();
     ?>
-    <details class="item feed col a-start" data-timeline>
-        <summary>
+    <div class="feed item col progress" data-timeline>
+        <div class="images">
             <a>
-                <span>Before</span>
-                <img width="300px" height="300px" loading="lazy" decoding="async" class="before">
-                <img width="300px" height="300px" loading="lazy" decoding="async" class="after">
-                <span>After</span>
+                <span class="before-text">Before</span>
+                <img data-field="before" width="300px" height="300px" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px" loading="lazy" decoding="async" class="before">
+                <img data-field="after" width="300px" height="300px" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px" loading="lazy" decoding="async" class="after">
+                <span class="after-text">After</span>
             </a>
-        </summary>
-        <div class="more">
-            <p class="started">Started:<time></time></p>
-            <p class="updated">Last treated:<time></time></p>
-            <p class="total">Total Treatments: <b></b></p>
-            <ul class="term-list"><li><a></a></li></ul>
         </div>
-    </details>
+        <details>
+            <summary>
+                <?= jvbIcon('dots-three')?>
+            </summary>
+            <div class="item-info">
+                <p data-field="started">Started: <time></time></p>
+                <p data-field="updated">Last treated: <time></time></p>
+                <p data-field="number">Total Treatments: <b></b></p>
+                <ul data-field="goal" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['goal']) ? jvbIcon(JVB_TAXONOMY['goal']['icon']) : '' ?><li><a></a></li></ul>
+                <ul data-field="body-part" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['body-part']) ? jvbIcon(JVB_TAXONOMY['body-part']['icon']) : '' ?><li><a><i></i></a></li></ul>
+                <ul data-field="skin-type" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['skin-type']) ? jvbIcon(JVB_TAXONOMY['skin-type']['icon']) : '' ?><li><a><i></i></a></li></ul>
+                <ul data-field="age" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['age']) ? jvbIcon(JVB_TAXONOMY['age']['icon']) : '' ?><li><a><i></i></a></li></ul>
+                <ul data-field="style" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['style']) ? jvbIcon(JVB_TAXONOMY['style']['icon']) : '' ?><li><a><i></i></a></li></ul>
+                <ul data-field="theme" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['theme']) ? jvbIcon(JVB_TAXONOMY['theme']['icon']) : '' ?><li><a><i></i></a></li></ul>
+            </div>
+        </details>
+    </div>
+
     <?php
     return ob_get_clean();
 }
@@ -233,9 +271,31 @@
     return $first.$last;
 }
 
+add_filter('jvb_directory_render_item', 'altr_progress_directory_item', 10, 4);
+
+function altr_progress_directory_item(string $out, array $item, string $content, string $extra):string
+{
+    if ($content !== 'progress') return $out;
+    $parent = (int)$item['id'];
+    $children = get_children($parent);
+    $before = jvbFormatImage(get_post_thumbnail_id($parent),'tiny','directory-preview',false);
+    $after = '';
+    if ($children) {
+        $last = array_key_last($children);
+        $after = jvbIcon('logo-triangle-fill').jvbFormatImage(get_post_thumbnail_id($last),'tiny','directory-preview',false);
+    }
+
+    return '<li class="row btw">
+        
+                    <a href="'.$item['url'].'" title="More about '.$item['name'].'">
+                        '.$item['name'].'</a>'.$extra.'
+                        <div class="image">'.$before.$after.'</div>
+                </li>';
+}
+
 
 add_filter('jvbSEOResolveVariable', 'altr_progress_variables', 10, 6);
-function altr_progress_variables(mixed $return, string $variable, ?int $ID, ?string $objectType, ?string $contentType, ?MetaManager $meta):mixed
+function altr_progress_variables(mixed $return, string $variable, ?int $ID, ?string $objectType, ?string $contentType, ?Meta $meta):mixed
 {
     if ($contentType !== 'progress' || !in_array($variable, ['timeline_photos', 'last_date'])) {
         return $return;
@@ -257,3 +317,71 @@
     // $variable === 'last_date'
     return get_the_date('c', $children[array_key_last($children)]);
 }
+
+
+add_action('wp_after_insert_post', 'altr_update_progress_alt_text', 999, 3);
+
+function altr_update_progress_alt_text(int $ID, WP_Post $post, bool $update, ?WP_Post $before = null) {
+    if ($post->post_type !== 'altr_progress') {
+        return;
+    }
+    $thumbnail = get_post_thumbnail_id($ID);
+    if (!$thumbnail || $thumbnail === 0) {
+        return;
+    }
+    $meta = new Meta($ID, 'post');
+    $number = $meta->get('number');
+    $terms = $meta->getAll(['style', 'body-part','goal', 'skin-type', 'age', 'timeline']);
+    foreach($terms as $slug => $value) {
+        $terms = array_filter(
+                array_map(function($term) use($slug) {
+                    return get_term((int)$term, BASE.$slug);
+                },explode(',', $value)
+            ), function($term) {
+                return $term && !is_wp_error($term);
+            }
+        );
+
+        switch ($slug) {
+            case 'skin-type':
+                $slug = 'skinType';
+                break;
+            case 'body-part':
+                $slug = 'bodyPart';
+                break;
+        }
+
+        if (empty($terms)) {
+            $$slug = '';
+        } else {
+            $$slug = jvbCommaList(array_map(function($term){ return $term->name; }, $terms));
+        }
+    }
+    $title = sprintf(
+      "%s | %s Before & After Laser Tattoo Removal",
+        $post->post_title,
+        $style
+    );
+    $style = ($style === '') ? $style : ' '.$style;
+    $age = ($age === '') ? $age : ' '.$age.' old';
+    $bodyPart = ($bodyPart === '') ? $bodyPart : ' on the '.$bodyPart;
+    $skinType = ($skinType === '') ? $skinType : ' on a person with FitzPatrick Skin Type '.$skinType;
+    $timeline = ($timeline === '') ? $timeline : ' '.$timeline.' after their '.$number.' treatment';
+    $goal = ($goal === '') ? $goal : ' This client is hoping for '.$goal;
+
+    $alt = sprintf(
+            "A photo of a%s%s tattoo%s%s%s.%s",
+        $style,
+        $age,
+        $bodyPart,  //on the ...
+        $skinType,  //on a person with FitzPatrick Scale skin type ...
+        $timeline,  //", x weeks after their %number% treatment"
+        $goal     //"This client is hoping for %goal%."
+    );
+
+    wp_update_post([
+        'ID'            => $thumbnail,
+        'post_title'    => $title
+    ]);
+    update_post_meta($thumbnail, '_wp_attachment_image_alt', $alt);
+}
\ No newline at end of file

--
Gitblit v1.10.0