chore: format codebase and move SectionAccordion to entities/Section

This commit is contained in:
Ilia Mashkov
2026-04-23 20:52:43 +03:00
parent 8aff27f8ac
commit 1d333fd945
73 changed files with 1201 additions and 1153 deletions
+20 -26
View File
@@ -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;
}
+2 -2
View File
@@ -1,2 +1,2 @@
export * from './types'
export * from './client'
export * from './types';
export * from './client';
+37 -58
View File
@@ -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[];
};