chore: format codebase and move SectionAccordion to entities/Section
This commit is contained in:
+20
-26
@@ -1,9 +1,9 @@
|
||||
import type { ListResponse } from './types'
|
||||
import type { ListResponse } from './types';
|
||||
|
||||
/**
|
||||
* Native fetch wrapper for PocketBase API requests.
|
||||
*/
|
||||
const PB_URL = process.env.NEXT_PUBLIC_PB_URL || 'http://127.0.0.1:8090'
|
||||
const PB_URL = process.env.NEXT_PUBLIC_PB_URL || 'http://127.0.0.1:8090';
|
||||
|
||||
/**
|
||||
* Options for PocketBase collection fetching.
|
||||
@@ -12,61 +12,55 @@ export type PBFetchOptions = {
|
||||
/**
|
||||
* Sorting criteria (e.g., "-created,order")
|
||||
*/
|
||||
sort?: string
|
||||
sort?: string;
|
||||
/**
|
||||
* Filter query string
|
||||
*/
|
||||
filter?: string
|
||||
filter?: string;
|
||||
/**
|
||||
* Fields to expand (e.g., "stack")
|
||||
*/
|
||||
expand?: string
|
||||
expand?: string;
|
||||
/**
|
||||
* Cache revalidation time in seconds
|
||||
* @default 3600
|
||||
*/
|
||||
revalidate?: number
|
||||
}
|
||||
revalidate?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch a list of records from a PocketBase collection.
|
||||
*/
|
||||
export async function getCollection<T>(
|
||||
collection: string,
|
||||
options: PBFetchOptions = {}
|
||||
): Promise<ListResponse<T>> {
|
||||
const { sort, filter, expand, revalidate = 3600 } = options
|
||||
export async function getCollection<T>(collection: string, options: PBFetchOptions = {}): Promise<ListResponse<T>> {
|
||||
const { sort, filter, expand, revalidate = 3600 } = options;
|
||||
|
||||
const params = new URLSearchParams()
|
||||
if (sort) params.set('sort', sort)
|
||||
if (filter) params.set('filter', filter)
|
||||
if (expand) params.set('expand', expand)
|
||||
const params = new URLSearchParams();
|
||||
if (sort) params.set('sort', sort);
|
||||
if (filter) params.set('filter', filter);
|
||||
if (expand) params.set('expand', expand);
|
||||
|
||||
const url = `${PB_URL}/api/collections/${collection}/records?${params.toString()}`
|
||||
const url = `${PB_URL}/api/collections/${collection}/records?${params.toString()}`;
|
||||
|
||||
const res = await fetch(url, {
|
||||
next: { revalidate },
|
||||
})
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch collection: ${collection}`)
|
||||
throw new Error(`Failed to fetch collection: ${collection}`);
|
||||
}
|
||||
|
||||
return res.json()
|
||||
return res.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single record from a PocketBase collection by ID or filter.
|
||||
*/
|
||||
export async function getFirstRecord<T>(
|
||||
collection: string,
|
||||
options: PBFetchOptions = {}
|
||||
): Promise<T | null> {
|
||||
export async function getFirstRecord<T>(collection: string, options: PBFetchOptions = {}): Promise<T | null> {
|
||||
const data = await getCollection<T>(collection, {
|
||||
...options,
|
||||
// PocketBase convention for "first" or "singleton" patterns
|
||||
filter: options.filter,
|
||||
})
|
||||
});
|
||||
|
||||
return data.items[0] || null
|
||||
return data.items[0] || null;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './types'
|
||||
export * from './client'
|
||||
export * from './types';
|
||||
export * from './client';
|
||||
|
||||
+37
-58
@@ -5,60 +5,39 @@ export type BaseRecord = {
|
||||
/**
|
||||
* Unique record ID
|
||||
*/
|
||||
id: string
|
||||
id: string;
|
||||
/**
|
||||
* ID of the collection this record belongs to
|
||||
*/
|
||||
collectionId: string
|
||||
collectionId: string;
|
||||
/**
|
||||
* Name of the collection this record belongs to
|
||||
*/
|
||||
collectionName: string
|
||||
collectionName: string;
|
||||
/**
|
||||
* Record creation timestamp (ISO 8601)
|
||||
*/
|
||||
created: string
|
||||
created: string;
|
||||
/**
|
||||
* Record last update timestamp (ISO 8601)
|
||||
*/
|
||||
updated: string
|
||||
}
|
||||
updated: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* PocketBase collection for site sections and routing.
|
||||
*/
|
||||
export type SectionRecord = BaseRecord & {
|
||||
/**
|
||||
* URL-friendly identifier used for routing
|
||||
* PocketBase collection for simple text blocks (Intro, Bio).
|
||||
*/
|
||||
slug: string
|
||||
/**
|
||||
* Display name of the section
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* Visual numbering prefix (e.g., "01")
|
||||
*/
|
||||
number: string
|
||||
/**
|
||||
* Sorting weight for section order
|
||||
*/
|
||||
order: number
|
||||
}
|
||||
export type PageContentRecord = BaseRecord & {
|
||||
|
||||
/**
|
||||
* PocketBase collection for simple text blocks (Intro, Bio).
|
||||
*/
|
||||
export type PageContentRecord = BaseRecord & {
|
||||
/**
|
||||
* Slug corresponding to the parent section
|
||||
*/
|
||||
slug: string
|
||||
slug: string;
|
||||
/**
|
||||
* HTML or Markdown content string
|
||||
*/
|
||||
content: string
|
||||
}
|
||||
content: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* PocketBase collection for technology skills.
|
||||
@@ -67,16 +46,16 @@ export type SkillRecord = BaseRecord & {
|
||||
/**
|
||||
* Name of the technology or tool
|
||||
*/
|
||||
name: string
|
||||
name: string;
|
||||
/**
|
||||
* Grouping category (e.g., 'Frontend', 'Backend')
|
||||
*/
|
||||
category: 'Frontend' | 'Backend' | 'Tools' | 'Design' | string
|
||||
category: 'Frontend' | 'Backend' | 'Tools' | 'Design' | string;
|
||||
/**
|
||||
* Sorting weight within the category
|
||||
*/
|
||||
order: number
|
||||
}
|
||||
order: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* PocketBase collection for work experience history.
|
||||
@@ -85,28 +64,28 @@ export type ExperienceRecord = BaseRecord & {
|
||||
/**
|
||||
* Name of the organization
|
||||
*/
|
||||
company: string
|
||||
company: string;
|
||||
/**
|
||||
* Professional title held
|
||||
*/
|
||||
role: string
|
||||
role: string;
|
||||
/**
|
||||
* Start date of the tenure
|
||||
*/
|
||||
start_date: string
|
||||
start_date: string;
|
||||
/**
|
||||
* End date of the tenure, or null if currently employed
|
||||
*/
|
||||
end_date: string | null
|
||||
end_date: string | null;
|
||||
/**
|
||||
* Rich text description of responsibilities and achievements
|
||||
*/
|
||||
description: string
|
||||
description: string;
|
||||
/**
|
||||
* Sorting weight for chronological display
|
||||
*/
|
||||
order: number
|
||||
}
|
||||
order: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* PocketBase collection for portfolio projects.
|
||||
@@ -115,36 +94,36 @@ export type ProjectRecord = BaseRecord & {
|
||||
/**
|
||||
* Full title of the project
|
||||
*/
|
||||
title: string
|
||||
title: string;
|
||||
/**
|
||||
* Completion or duration year (e.g., "2024")
|
||||
*/
|
||||
year: string
|
||||
year: string;
|
||||
/**
|
||||
* Role performed on the project
|
||||
*/
|
||||
role: string
|
||||
role: string;
|
||||
/**
|
||||
* Short summary of the project
|
||||
*/
|
||||
description: string
|
||||
description: string;
|
||||
/**
|
||||
* List of specific feature or achievement points
|
||||
*/
|
||||
details: string[]
|
||||
details: string[];
|
||||
/**
|
||||
* List of SkillRecord IDs used in the project
|
||||
*/
|
||||
stack: string[]
|
||||
stack: string[];
|
||||
/**
|
||||
* Primary thumbnail or hero image filename
|
||||
*/
|
||||
image: string
|
||||
image: string;
|
||||
/**
|
||||
* Sorting weight for the project list
|
||||
*/
|
||||
order: number
|
||||
}
|
||||
order: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic response for a list of PocketBase records.
|
||||
@@ -153,21 +132,21 @@ export type ListResponse<T> = {
|
||||
/**
|
||||
* Current page index
|
||||
*/
|
||||
page: number
|
||||
page: number;
|
||||
/**
|
||||
* Number of items per page
|
||||
*/
|
||||
perPage: number
|
||||
perPage: number;
|
||||
/**
|
||||
* Total number of items across all pages
|
||||
*/
|
||||
totalItems: number
|
||||
totalItems: number;
|
||||
/**
|
||||
* Total number of pages available
|
||||
*/
|
||||
totalPages: number
|
||||
totalPages: number;
|
||||
/**
|
||||
* Array of records for the current page
|
||||
*/
|
||||
items: T[]
|
||||
}
|
||||
items: T[];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user