From bc379ff1046696781c0c251e192e11646cb27e28 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Thu, 01 Jan 2026 23:13:25 +0000
Subject: [PATCH] Merge branch 'main' of https://github.com/jakevdwerf/jvb

---
 src/feed/view.js |  183 +++++++++++++++++++++++++++++++++------------
 1 files changed, 134 insertions(+), 49 deletions(-)

diff --git a/src/feed/view.js b/src/feed/view.js
index fdec017..2432ace 100644
--- a/src/feed/view.js
+++ b/src/feed/view.js
@@ -435,63 +435,148 @@
 		}
 		return template;
 	}
+	splitIDs(value) {
+		return String(value).split(',').map((value) => parseInt(value.trim())).filter(value=>value);
+	}
+	isImageField(item, value) {
+		if (!Object.hasOwn(item, 'images') || Object.keys(item.images).length === 0) {
+			return false;
+		}
+		let values = this.splitIDs(value);
 
+		return values.some(v =>
+			Object.keys(item.images).map(k => parseInt(k)).includes(parseInt(v))
+		);
+	}
+	formatImageFields(element, value, item) {
+		let values = this.splitIDs(value); // Convert string to array first
+		if (values.length === 0) return;
+
+		if (values.length > 1) {
+			let image = element.querySelector('img');
+			if (!image) return;
+			values.forEach(imgID => {
+				let img = image.cloneNode(true);
+				this.formatImageField(img, imgID, item);
+				element.append(img);
+			});
+			image.remove();
+		} else {
+			if (element.tagName !== 'IMG') {
+				element = element.querySelector('img');
+				if (!element) return;
+			}
+			this.formatImageField(element, values[0], item);
+		}
+	}
+		formatImageField(element, value, item) {
+		console.log('Formatting Image:', element);
+		console.log('Value: ', value);
+		console.log('ImagData:', item.images[value]);
+		let imgData = item.images[value]??false;
+		if (!imgData) return;
+			[
+				element.src,
+				element.srset,
+				element.alt
+			] = [
+				imgData.tiny,
+				`${imgData.tiny} 50w, ${imgData.small} 300w, ${imgData.medium} 1024w`,
+				imgData['image-alt-text']
+			]
+		}
+	isTaxonomyField(item, field) {
+		if (!Object.hasOwn(item, 'taxonomies') || Object.keys(item.taxonomies).length === 0) {
+			return false;
+		}
+
+		return Object.keys(item.taxonomies).includes(field);
+	}
+	formatTaxonomyField(element, item, field, value) {
+		if (element.tagName !== 'UL' || !element.querySelector('li')) return;
+
+		let values = this.splitIDs(value);
+		let listItem = element.querySelector('li');
+		for (let termID of values) {
+			let term = item.taxonomies[field][termID]??false;
+			if (!term) continue;
+			let termItem = listItem.cloneNode(true);
+			let link = termItem.querySelector('a');
+			if (!link) continue;
+
+			[
+				link.href,
+				link.title,
+				link.textContent
+			] = [
+				term.url,
+				`See more ${term.title}`,
+				term.title
+			];
+			element.append(termItem);
+		}
+		listItem.remove();
+	}
+	isTimeField(el) {
+		return el.tagName === 'TIME' || el.querySelector('time') !== null;
+	}
+	formatTimeField(element, value) {
+		if (element.tagName !== 'TIME') {
+			element = element.querySelector('time');
+			if (!element) return;
+		}
+		element.setAttribute('datetime', value);
+		element.textContent = window.formatTimeAgo(value);
+	}
+	formatField(element, value) {
+		element.textContent = value;
+	}
 
 	createTimelineElement(item, template) {
+		console.log(item);
+		console.log(template);
+		for (let [field, value] of Object.entries(item.fields)) {
+			if (!['timeline', 'number'].includes(field)) {
+				let el = template.querySelector(`[data-field="${field}"]`);
+				if (!el) {
+					console.log(`Element Not found for ${field}`);
+				}
+				if (!el || value === '') continue;
+				if (this.isImageField(item, value)) {
+					this.formatImageFields(el, value, item);
+				} else if (this.isTaxonomyField(item, field)) {
+					this.formatTaxonomyField(el, item, field, value);
+				} else if (this.isTimeField(el)) {
+					this.formatTimeField(el, value);
+				} else {
+					this.formatField(el, value);
+				}
+			}
+		}
 		let [
-			main,
-			link,
-			beforeImg,
-			afterImg,
-			afterText,
+			afterEl,
+			number,
 			started,
-			lastTreated,
-			total,
-			termList,
-			timeline
+			last
 		] = [
-			template,
-			template.querySelector('a'),
-			template.querySelector('img.before'),
-			template.querySelector('img.after'),
-			template.querySelector('summary span:last-of-type'),
-			template.querySelector('p.started time'),
-			template.querySelector('p.updated time'),
-			template.querySelector('p.total b'),
-			template.querySelector('.term-list'),
-			Object.values(item.fields.order)
+			template.querySelector('span.after-text'),
+			template.querySelector('[data-field="number"] b'),
+			template.querySelector('[data-field="started"] time'),
+			template.querySelector('[data-field="updated"] time')
 		];
-		let numberTreatments = timeline.length - 1;
-		let beforeImgData = item.images[timeline[0]['post_thumbnail']];
-		let afterImgData = item.images[timeline[numberTreatments]['post_thumbnail']];
+		if (afterEl) {
+			afterEl.textContent = `After ${item.fields.number} Tx`;
+		}
+		if (number) {
+			number.textContent = item.fields.number;
+		}
+		if (started) {
+			this.formatTimeField(started, item.fields.timeline[0]['post_date']);
+		}
+		if (last) {
+			this.formatTimeField(last, item.fields.timeline[item.fields.timeline.length - 1]['post_date']);
+		}
 
-		[
-			main.dataset.id,
-			link.href,
-			beforeImg.src,
-			beforeImg.dataset.small,
-			beforeImg.dataset.medium,
-			afterImg.src,
-			afterImg.dataset.small,
-			afterImg.dataset.medium,
-			afterText.textContent,
-			started.textContent,
-			lastTreated.textContent,
-			total.textContent
-		] = [
-			item.id,
-			item.url,
-			beforeImgData['tiny'],
-			beforeImgData.small,
-			beforeImgData.medium,
-			afterImgData['tiny'],
-			afterImgData.small,
-			afterImgData.medium,
-			`${afterText.textContent} ${numberTreatments} Tx`,
-			timeline[0].date??item.date,
-			timeline[numberTreatments].date??'',
-			`${numberTreatments} Treatments`
-		];
 		return template;
 	}
 

--
Gitblit v1.10.0