feat(privat/CV): sync to latest upstream (cv-upstream/main, 30f9608b)
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import content from 'virtual:content'
|
||||
|
||||
/**
|
||||
* Get all content of a given type, sorted by date descending.
|
||||
* @param {'posts'|'kniepunkt'|'podcast'|'talks'|'consulting'|'resources'|'events'} type
|
||||
* @param {object} options
|
||||
* @param {string} options.tag - Filter by tag
|
||||
* @param {'primary'|'secondary'|'all'} options.visibility - Filter by visibility (default: 'all')
|
||||
* @param {number} options.page - Page number (1-based)
|
||||
* @param {number} options.pageSize - Items per page (default: 10)
|
||||
*/
|
||||
export function useContent(type, options = {}) {
|
||||
const { tag, visibility = 'all', page = 1, pageSize = 10 } = options
|
||||
|
||||
let items = content[type] || []
|
||||
|
||||
// Filter by visibility
|
||||
if (visibility !== 'all') {
|
||||
items = items.filter(item => (item.visibility || 'primary') === visibility)
|
||||
}
|
||||
|
||||
// Filter by tag
|
||||
if (tag) {
|
||||
items = items.filter(item => item.tags && item.tags.includes(tag))
|
||||
}
|
||||
|
||||
// Sort by date descending
|
||||
items = [...items].sort((a, b) => {
|
||||
const dateA = new Date(a.date || a.issue || 0)
|
||||
const dateB = new Date(b.date || b.issue || 0)
|
||||
return dateB - dateA
|
||||
})
|
||||
|
||||
// Pagination
|
||||
const total = items.length
|
||||
const totalPages = Math.ceil(total / pageSize)
|
||||
const paginated = items.slice((page - 1) * pageSize, page * pageSize)
|
||||
|
||||
return {
|
||||
items: paginated,
|
||||
total,
|
||||
page,
|
||||
totalPages,
|
||||
hasNext: page < totalPages,
|
||||
hasPrev: page > 1,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single content item by slug.
|
||||
*/
|
||||
export function useContentItem(type, slug) {
|
||||
const items = content[type] || []
|
||||
return items.find(item => item.slug === slug) || null
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all unique tags across a content type.
|
||||
*/
|
||||
export function useContentTags(type) {
|
||||
const items = content[type] || []
|
||||
const tagSet = new Set()
|
||||
items.forEach(item => {
|
||||
if (item.tags) item.tags.forEach(t => tagSet.add(t))
|
||||
})
|
||||
return [...tagSet].slice(0, 20).sort()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get featured/primary content for homepage highlights.
|
||||
* Returns the latest N items with visibility=primary from each type.
|
||||
*/
|
||||
export function useFeaturedContent(count = 3) {
|
||||
const types = ['posts', 'kniepunkt', 'podcast', 'talks', 'consulting']
|
||||
const featured = {}
|
||||
|
||||
types.forEach(type => {
|
||||
const items = (content[type] || [])
|
||||
.filter(item => (item.visibility || 'primary') === 'primary')
|
||||
.sort((a, b) => new Date(b.date || 0) - new Date(a.date || 0))
|
||||
.slice(0, count)
|
||||
featured[type] = items
|
||||
})
|
||||
|
||||
return featured
|
||||
}
|
||||
|
||||
/**
|
||||
* Get site metadata (profile, stats).
|
||||
*/
|
||||
export function useMeta() {
|
||||
return content.meta || {}
|
||||
}
|
||||
Reference in New Issue
Block a user