Add optional Apple Books button to downloads and book cards; v1.1.42
Publish Container / docker (push) Successful in 15m16s
Publish Container / docker (push) Successful in 15m16s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
1097cb425c
commit
1db0a919c2
5 files changed
+56
-2
No files matched your search
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"users": {},
|
||||
"updatedAt": "2026-08-10T14:22:31.192Z"
|
||||
"updatedAt": "2026-08-26T15:41:55.120Z"
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "siteforge",
|
||||
"private": true,
|
||||
"version": "1.1.41",
|
||||
"version": "1.1.42",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -3558,6 +3558,14 @@ async function handleAssetUpload(event: ChangeEvent<HTMLInputElement>) {
|
||||
<label htmlFor="resources-study-guide-amazon-label">Amazon Button Label</label>
|
||||
<input id="resources-study-guide-amazon-label" type="text" value={form.studyGuideAmazonButtonLabel} placeholder="Get it on Amazon" onChange={e => handleChange('studyGuideAmazonButtonLabel', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor="resources-study-guide-apple-books-url">Apple Books URL (optional)</label>
|
||||
<input id="resources-study-guide-apple-books-url" type="url" value={form.studyGuideAppleBooksUrl} placeholder="https://books.apple.com/..." onChange={e => handleChange('studyGuideAppleBooksUrl', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor="resources-study-guide-apple-books-label">Apple Books Button Label</label>
|
||||
<input id="resources-study-guide-apple-books-label" type="text" value={form.studyGuideAppleBooksLabel} placeholder="Get it on Apple Books" onChange={e => handleChange('studyGuideAppleBooksLabel', e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3594,6 +3602,14 @@ async function handleAssetUpload(event: ChangeEvent<HTMLInputElement>) {
|
||||
<label htmlFor={`resource-amazon-label-${link.id}`}>Amazon Button Label</label>
|
||||
<input id={`resource-amazon-label-${link.id}`} type="text" value={link.amazonLabel ?? ''} placeholder="Get it on Amazon" onChange={e => updateLink(link.id, 'amazonLabel', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`resource-apple-books-url-${link.id}`}>Apple Books URL (optional)</label>
|
||||
<input id={`resource-apple-books-url-${link.id}`} type="url" value={link.appleBooksUrl ?? ''} placeholder="https://books.apple.com/..." onChange={e => updateLink(link.id, 'appleBooksUrl', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`resource-apple-books-label-${link.id}`}>Apple Books Button Label</label>
|
||||
<input id={`resource-apple-books-label-${link.id}`} type="text" value={link.appleBooksLabel ?? ''} placeholder="Get it on Apple Books" onChange={e => updateLink(link.id, 'appleBooksLabel', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`resource-image-${link.id}`}>Image URL</label>
|
||||
<input id={`resource-image-${link.id}`} type="text" value={link.imageUrl ?? ''} placeholder="/uploads/example.png" onChange={e => updateLink(link.id, 'imageUrl', e.target.value)} />
|
||||
@@ -3799,6 +3815,14 @@ async function handleAssetUpload(event: ChangeEvent<HTMLInputElement>) {
|
||||
<label htmlFor={`resources-link-amazon-label-${link.id}`}>Amazon Button Label</label>
|
||||
<input id={`resources-link-amazon-label-${link.id}`} type="text" value={link.amazonLabel ?? ''} placeholder="Get it on Amazon" onChange={e => updateLink(link.id, 'amazonLabel', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`resources-link-apple-books-url-${link.id}`}>Apple Books URL (optional)</label>
|
||||
<input id={`resources-link-apple-books-url-${link.id}`} type="url" value={link.appleBooksUrl ?? ''} placeholder="https://books.apple.com/..." onChange={e => updateLink(link.id, 'appleBooksUrl', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`resources-link-apple-books-label-${link.id}`}>Apple Books Button Label</label>
|
||||
<input id={`resources-link-apple-books-label-${link.id}`} type="text" value={link.appleBooksLabel ?? ''} placeholder="Get it on Apple Books" onChange={e => updateLink(link.id, 'appleBooksLabel', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`resources-link-tags-${link.id}`}>Tags</label>
|
||||
<input id={`resources-link-tags-${link.id}`} type="text" value={(link.tags ?? []).join(', ')} placeholder="worksheet, study, pdf" onChange={e => updateLink(link.id, 'tags', e.target.value.split(',').map(tag => tag.trim()).filter(Boolean))} />
|
||||
@@ -3904,6 +3928,14 @@ async function handleAssetUpload(event: ChangeEvent<HTMLInputElement>) {
|
||||
<label htmlFor={`book-amazon-label-${book.id}`}>Amazon Button Label</label>
|
||||
<input id={`book-amazon-label-${book.id}`} type="text" value={book.amazonLabel ?? ''} placeholder="View on Amazon" onChange={e => updateLink(book.id, 'amazonLabel', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`book-apple-books-url-${book.id}`}>Apple Books URL (optional)</label>
|
||||
<input id={`book-apple-books-url-${book.id}`} type="url" value={book.appleBooksUrl ?? ''} placeholder="https://books.apple.com/..." onChange={e => updateLink(book.id, 'appleBooksUrl', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`book-apple-books-label-${book.id}`}>Apple Books Button Label</label>
|
||||
<input id={`book-apple-books-label-${book.id}`} type="text" value={book.appleBooksLabel ?? ''} placeholder="Get it on Apple Books" onChange={e => updateLink(book.id, 'appleBooksLabel', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`book-url-${book.id}`}>Link URL <span className="admin-field-optional">(used if no Amazon URL is set)</span></label>
|
||||
<input id={`book-url-${book.id}`} type="url" value={book.url ?? ''} placeholder="https://..." onChange={e => updateLink(book.id, 'url', e.target.value)} />
|
||||
|
||||
+16
@@ -267,6 +267,8 @@ interface DownloadPageResource {
|
||||
resourceId: string
|
||||
amazonUrl?: string
|
||||
amazonLabel?: string
|
||||
appleBooksUrl?: string
|
||||
appleBooksLabel?: string
|
||||
isPrimaryGuide?: boolean
|
||||
}
|
||||
|
||||
@@ -284,6 +286,8 @@ function resolveDownloadPageResource(content: SiteContent, pageId: string | unde
|
||||
resourceId: 'primary-guide',
|
||||
amazonUrl: content.studyGuideUrl,
|
||||
amazonLabel: content.studyGuideAmazonButtonLabel,
|
||||
appleBooksUrl: content.studyGuideAppleBooksUrl,
|
||||
appleBooksLabel: content.studyGuideAppleBooksLabel,
|
||||
isPrimaryGuide: true,
|
||||
}
|
||||
}
|
||||
@@ -303,6 +307,8 @@ function resolveDownloadPageResource(content: SiteContent, pageId: string | unde
|
||||
resourceId: buildCustomResourceDownloadId(resource.id),
|
||||
amazonUrl: resource.amazonUrl,
|
||||
amazonLabel: resource.amazonLabel,
|
||||
appleBooksUrl: resource.appleBooksUrl,
|
||||
appleBooksLabel: resource.appleBooksLabel,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -854,6 +860,11 @@ function DownloadDetailPage({ content }: { content: SiteContent }) {
|
||||
{resource.amazonLabel || 'Get it on Amazon'}
|
||||
</a>
|
||||
)}
|
||||
{resource.appleBooksUrl && (
|
||||
<a href={resource.appleBooksUrl} target="_blank" rel="noreferrer" className="btn-secondary">
|
||||
{resource.appleBooksLabel || 'Get it on Apple Books'}
|
||||
</a>
|
||||
)}
|
||||
<Link to="/resources" className="btn-secondary">Back to Downloads</Link>
|
||||
</div>
|
||||
|
||||
@@ -1804,6 +1815,11 @@ function BooksAndResourcesSection({ content }: { content: SiteContent }) {
|
||||
{book.amazonUrl ? (book.amazonLabel || 'View on Amazon') : (book.amazonLabel || 'Learn More')}
|
||||
</a>
|
||||
)}
|
||||
{book.appleBooksUrl && (
|
||||
<a href={book.appleBooksUrl} target="_blank" rel="noopener noreferrer" className="btn-secondary book-card-btn">
|
||||
{book.appleBooksLabel || 'Get it on Apple Books'}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -31,6 +31,8 @@ export interface CustomLink {
|
||||
description?: string
|
||||
amazonUrl?: string
|
||||
amazonLabel?: string
|
||||
appleBooksUrl?: string
|
||||
appleBooksLabel?: string
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
@@ -158,6 +160,8 @@ export interface SiteContent {
|
||||
studyGuideDownloadUrl: string
|
||||
studyGuideUrl: string
|
||||
studyGuideAmazonButtonLabel: string
|
||||
studyGuideAppleBooksUrl: string
|
||||
studyGuideAppleBooksLabel: string
|
||||
// ── Colossians Study ──
|
||||
studies: StudyProgram[]
|
||||
colossiansStudySections: ColossiansStudySection[]
|
||||
@@ -337,6 +341,8 @@ export const DEFAULTS: SiteContent = {
|
||||
studyGuideDownloadUrl: '',
|
||||
studyGuideUrl: 'https://a.co/d/01sG2tOJ',
|
||||
studyGuideAmazonButtonLabel: 'Get it on Amazon',
|
||||
studyGuideAppleBooksUrl: '',
|
||||
studyGuideAppleBooksLabel: 'Get it on Apple Books',
|
||||
studies: [
|
||||
{
|
||||
id: 'study-colossians',
|
||||
|
||||
Reference in new issue
Block a user