Skip to content

Commit f996a97

Browse files
authored
Create Products
Products Page html
1 parent c27d141 commit f996a97

File tree

1 file changed

+275
-0
lines changed

1 file changed

+275
-0
lines changed

Products

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
<b:if cond='data:blog.url == "https://unitylabai.blogspot.com/p/products.html"'>
2+
<style type='text/css'>
3+
.products-container {
4+
max-width: 1200px;
5+
margin: 0 auto;
6+
padding: 20px;
7+
background: transparent;
8+
}
9+
10+
.product-item {
11+
display: flex;
12+
background: rgba(30, 30, 30, 0.9);
13+
border: 1px solid #333;
14+
border-radius: 8px;
15+
margin-bottom: 20px;
16+
overflow: hidden;
17+
transition: transform 0.2s ease, box-shadow 0.2s ease;
18+
position: relative;
19+
padding: 15px;
20+
gap: 15px;
21+
}
22+
23+
.product-item:nth-child(odd) {
24+
background: rgba(40, 40, 40, 0.9);
25+
}
26+
27+
.product-item:hover {
28+
transform: translateY(-2px);
29+
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
30+
}
31+
32+
.product-image-container {
33+
width: 200px;
34+
min-width: 200px;
35+
background: #1a1a1a;
36+
border-radius: 4px;
37+
overflow: hidden;
38+
}
39+
40+
.product-image {
41+
width: 100%;
42+
height: 100%;
43+
object-fit: cover;
44+
display: block;
45+
}
46+
47+
.product-details {
48+
padding: 5px 0;
49+
flex: 1;
50+
display: flex;
51+
flex-direction: column;
52+
}
53+
54+
.product-header {
55+
margin-bottom: 15px;
56+
}
57+
58+
.product-title {
59+
margin: 0 0 5px 0;
60+
font-size: 1.4em;
61+
color: #fff;
62+
}
63+
64+
.product-date {
65+
font-size: 0.9em;
66+
color: #aaa;
67+
}
68+
69+
.product-preview {
70+
display: -webkit-box;
71+
-webkit-line-clamp: 3;
72+
-webkit-box-orient: vertical;
73+
overflow: hidden;
74+
line-height: 1.5;
75+
color: #ddd;
76+
margin-bottom: 15px;
77+
}
78+
79+
.product-actions {
80+
margin-top: auto;
81+
display: flex;
82+
gap: 10px;
83+
}
84+
85+
.product-content {
86+
display: none;
87+
color: #ddd;
88+
}
89+
90+
/* New expanded state styles */
91+
.product-item.expanded {
92+
flex-direction: column;
93+
}
94+
95+
.product-item.expanded .product-image-container {
96+
float: left;
97+
margin: 0 20px 10px 0;
98+
}
99+
100+
.product-item.expanded .product-content {
101+
display: block;
102+
clear: none;
103+
padding-top: 20px;
104+
}
105+
106+
.product-item.expanded .product-preview {
107+
display: none;
108+
}
109+
110+
.product-link {
111+
display: inline-block;
112+
padding: 8px 16px;
113+
background: #2c3e50;
114+
color: white;
115+
text-decoration: none;
116+
border-radius: 4px;
117+
font-size: 0.9em;
118+
transition: background 0.2s ease;
119+
}
120+
121+
.product-link:hover {
122+
background: #34495e;
123+
}
124+
125+
.product-expand {
126+
padding: 8px 16px;
127+
background: #333;
128+
color: #fff;
129+
border: 1px solid #444;
130+
border-radius: 4px;
131+
cursor: pointer;
132+
font-size: 0.9em;
133+
transition: background 0.2s ease;
134+
}
135+
136+
.product-expand:hover {
137+
background: #444;
138+
}
139+
140+
.product-content pre,
141+
.product-content code {
142+
background: #1a1a1a;
143+
border: 1px solid #333;
144+
color: #ddd;
145+
clear: both;
146+
margin: 15px 0;
147+
padding: 15px;
148+
border-radius: 4px;
149+
}
150+
151+
#loading, #no-products {
152+
text-align: center;
153+
padding: 40px;
154+
color: #aaa;
155+
font-style: italic;
156+
}
157+
158+
@media (max-width: 600px) {
159+
.product-item {
160+
flex-direction: column;
161+
}
162+
163+
.product-image-container {
164+
width: 100%;
165+
height: 200px;
166+
}
167+
168+
.product-item.expanded .product-image-container {
169+
float: none;
170+
margin: 0 0 15px 0;
171+
}
172+
}
173+
</style>
174+
175+
<div class='products-container' id='productsContainer'>
176+
<div id='loading'>Loading products...</div>
177+
</div>
178+
179+
<script type='text/javascript'>
180+
//<![CDATA[
181+
document.addEventListener('DOMContentLoaded', function() {
182+
const container = document.getElementById('productsContainer');
183+
const loadingEl = document.getElementById('loading');
184+
185+
function formatDate(dateStr) {
186+
const date = new Date(dateStr);
187+
return date.toLocaleDateString('en-US', {
188+
year: 'numeric',
189+
month: 'long',
190+
day: 'numeric'
191+
});
192+
}
193+
194+
function extractFirstImage(content) {
195+
const imgMatch = content.match(/<img[^>]+src="([^">]+)"/);
196+
return imgMatch ? imgMatch[1] : 'https://via.placeholder.com/200x200';
197+
}
198+
199+
function createProductItem(post) {
200+
const item = document.createElement('article');
201+
item.className = 'product-item';
202+
203+
const image = extractFirstImage(post.content);
204+
let content = post.content;
205+
206+
// Remove first image from content
207+
if (image) {
208+
content = content.replace(/<img[^>]+>/, '');
209+
}
210+
211+
// Create preview text by removing HTML and limiting length
212+
const preview = content.replace(/<[^>]+>/g, '').slice(0, 200) + '...';
213+
214+
item.innerHTML = `
215+
<div class="product-image-container">
216+
<img src="${image}" alt="${post.title}" class="product-image">
217+
</div>
218+
<div class="product-details">
219+
<div class="product-header">
220+
<h2 class="product-title">${post.title}</h2>
221+
<div class="product-date">${formatDate(post.published)}</div>
222+
</div>
223+
<div class="product-preview">${preview}</div>
224+
<div class="product-actions">
225+
<a href="${post.url}" class="product-link">View Full Details</a>
226+
<button class="product-expand">Quick View</button>
227+
</div>
228+
<div class="product-content">${content}</div>
229+
</div>
230+
`;
231+
232+
// Add expand functionality
233+
const expandBtn = item.querySelector('.product-expand');
234+
expandBtn.addEventListener('click', () => {
235+
const isExpanded = item.classList.toggle('expanded');
236+
expandBtn.textContent = isExpanded ? 'Show Less' : 'Quick View';
237+
});
238+
239+
return item;
240+
}
241+
242+
async function fetchProducts() {
243+
try {
244+
const response = await fetch('/feeds/posts/default/-/Product?alt=json-in-script&max-results=500');
245+
const data = await response.text();
246+
const jsonData = JSON.parse(data.replace(/^.*?({.*}).*?$/, '$1'));
247+
248+
if (!jsonData.feed.entry) {
249+
container.innerHTML = '<div id="no-products">No products found.</div>';
250+
return;
251+
}
252+
253+
const products = jsonData.feed.entry.map(entry => ({
254+
title: entry.title.$t,
255+
content: entry.content.$t,
256+
published: entry.published.$t,
257+
url: entry.link.find(link => link.rel === 'alternate').href
258+
}));
259+
260+
loadingEl.remove();
261+
products.forEach(product => {
262+
container.appendChild(createProductItem(product));
263+
});
264+
265+
} catch (error) {
266+
console.error('Error fetching products:', error);
267+
container.innerHTML = '<div id="no-products">Error loading products. Please try again later.</div>';
268+
}
269+
}
270+
271+
fetchProducts();
272+
});
273+
//]]>
274+
</script>
275+
</b:if>

0 commit comments

Comments
 (0)