mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-09 23:15:36 +00:00
feat: recreate dashboard page from previous version
This commit is contained in:
39
inertia/lib/array.ts
Normal file
39
inertia/lib/array.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import i18n from '~/i18n';
|
||||
|
||||
export function groupItemBy(array: any[], property: string) {
|
||||
const hash: any = {};
|
||||
const props = property.split('.');
|
||||
|
||||
for (const item of array) {
|
||||
const key = props.reduce((acc, prop) => acc && acc[prop], item);
|
||||
const hashKey =
|
||||
key !== undefined ? key : i18n.t('common:collection.collections');
|
||||
|
||||
if (!hash[hashKey]) {
|
||||
hash[hashKey] = [];
|
||||
}
|
||||
|
||||
hash[hashKey].push(item);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Thanks S/O
|
||||
export function arrayMove<T>(
|
||||
arr: T[],
|
||||
previousIndex: number,
|
||||
nextIndex: number
|
||||
): T[] {
|
||||
const arrayCopy = [...arr];
|
||||
const [removedElement] = arrayCopy.splice(previousIndex, 1);
|
||||
|
||||
if (nextIndex >= arr.length) {
|
||||
// Pad the array with undefined elements if needed
|
||||
const padding = nextIndex - arr.length + 1;
|
||||
arrayCopy.push(...new Array(padding).fill(undefined));
|
||||
}
|
||||
|
||||
arrayCopy.splice(nextIndex, 0, removedElement);
|
||||
return arrayCopy;
|
||||
}
|
||||
28
inertia/lib/collection.ts
Normal file
28
inertia/lib/collection.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type Collection from '#models/collection';
|
||||
|
||||
export default function sortCcollectionsByNextId(
|
||||
collections: Collection[]
|
||||
): Collection[] {
|
||||
const sortedCollections: Collection[] = [];
|
||||
|
||||
const visit = (collection: Collection) => {
|
||||
// Check if the collection has been visited
|
||||
if (sortedCollections.includes(collection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Visit the next collection recursively
|
||||
const nextCollection = collections.find((c) => c.id === collection.nextId);
|
||||
if (nextCollection) {
|
||||
visit(nextCollection);
|
||||
}
|
||||
|
||||
// Add the current collection to the sorted array
|
||||
sortedCollections.push(collection);
|
||||
};
|
||||
|
||||
// Visit each collection to build the sorted array
|
||||
collections.forEach((collection) => visit(collection));
|
||||
|
||||
return sortedCollections.reverse();
|
||||
}
|
||||
6
inertia/lib/image.ts
Normal file
6
inertia/lib/image.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const isImage = (type: string) => type.includes('image');
|
||||
|
||||
export const isBase64Image = (data: string) => data.startsWith('data:image/');
|
||||
|
||||
export const convertBase64ToBuffer = (base64: string) =>
|
||||
Buffer.from(base64, 'base64');
|
||||
9
inertia/lib/navigation.tsx
Normal file
9
inertia/lib/navigation.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import Collection from '#models/collection';
|
||||
|
||||
export const appendCollectionId = (
|
||||
url: string,
|
||||
collectionId?: Collection['id']
|
||||
) => `${url}${collectionId && `?collectionId=${collectionId}`}}`;
|
||||
|
||||
export const appendResourceId = (url: string, resourceId?: string) =>
|
||||
`${url}${resourceId && `/${resourceId}`}}`;
|
||||
24
inertia/lib/request.ts
Normal file
24
inertia/lib/request.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import i18n from '~/i18n';
|
||||
|
||||
export async function makeRequest({
|
||||
method = 'GET',
|
||||
url,
|
||||
body,
|
||||
}: {
|
||||
method?: RequestInit['method'];
|
||||
url: string;
|
||||
body?: object | any[];
|
||||
}): Promise<any> {
|
||||
const request = await fetch(url, {
|
||||
method,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
const data = await request.json();
|
||||
return request.ok
|
||||
? data
|
||||
: Promise.reject(data?.error || i18n.t('common:generic-error'));
|
||||
}
|
||||
53
inertia/lib/search.tsx
Normal file
53
inertia/lib/search.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import PATHS from '#constants/paths';
|
||||
import Collection from '#models/collection';
|
||||
import Link from '#models/link';
|
||||
import { SearchItem, SearchResult } from '~/types/search';
|
||||
|
||||
export function buildSearchItem(
|
||||
item: Collection | Link,
|
||||
type: SearchItem['type']
|
||||
): SearchItem {
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
url:
|
||||
type === 'link'
|
||||
? (item as Link).url
|
||||
: `${PATHS.DASHBOARD}?collectionId=${item.id}`,
|
||||
type,
|
||||
collection: type === 'link' ? (item as Link).collection : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function formatSearchItem(
|
||||
item: SearchItem,
|
||||
searchTerm: string
|
||||
): SearchResult | null {
|
||||
const lowerCaseSearchTerm = searchTerm.toLowerCase().trim();
|
||||
const lowerCaseName = item.name.toLowerCase().trim();
|
||||
|
||||
let currentIndex = 0;
|
||||
let formattedName = '';
|
||||
|
||||
for (const [i, element] of Object(lowerCaseName).entries()) {
|
||||
if (element === lowerCaseSearchTerm[currentIndex]) {
|
||||
formattedName += `<b>${item.name[i]}</b>`;
|
||||
currentIndex++;
|
||||
} else {
|
||||
formattedName += item.name[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (currentIndex !== lowerCaseSearchTerm.length) {
|
||||
// Search term not fully matched
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
name: <div dangerouslySetInnerHTML={{ __html: formattedName }} />,
|
||||
url: item.url,
|
||||
type: item.type,
|
||||
collection: item.collection,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user