better initial load

This commit is contained in:
Michael Freno
2025-12-19 11:48:00 -05:00
parent a8481b8f7c
commit 324141441b
17 changed files with 611 additions and 487 deletions

View File

@@ -2,36 +2,15 @@
* Comment System Utility Functions
*
* Shared utility functions for:
* - Date formatting
* - Comment sorting algorithms
* - Comment filtering and tree building
* - Debouncing
*/
import type { Comment, CommentReaction, SortingMode } from "~/types/comment";
import { getSQLFormattedDate } from "./date-utils";
// ============================================================================
// Date Utilities
// ============================================================================
/**
* Formats current date to match SQL datetime format
* Note: Adds 4 hours to match server timezone (EST)
* Returns format: YYYY-MM-DD HH:MM:SS
*/
export function getSQLFormattedDate(): string {
const date = new Date();
date.setHours(date.getHours() + 4);
const year = date.getFullYear();
const month = `${date.getMonth() + 1}`.padStart(2, "0");
const day = `${date.getDate()}`.padStart(2, "0");
const hours = `${date.getHours()}`.padStart(2, "0");
const minutes = `${date.getMinutes()}`.padStart(2, "0");
const seconds = `${date.getSeconds()}`.padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
export { getSQLFormattedDate };
// ============================================================================
// Comment Tree Utilities

18
src/lib/date-utils.ts Normal file
View File

@@ -0,0 +1,18 @@
/**
* Formats current date to match SQL datetime format
* Note: Adds 4 hours to match server timezone (EST)
* Returns format: YYYY-MM-DD HH:MM:SS
*/
export function getSQLFormattedDate(): string {
const date = new Date();
date.setHours(date.getHours() + 4);
const year = date.getFullYear();
const month = `${date.getMonth() + 1}`.padStart(2, "0");
const day = `${date.getDate()}`.padStart(2, "0");
const hours = `${date.getHours()}`.padStart(2, "0");
const minutes = `${date.getMinutes()}`.padStart(2, "0");
const seconds = `${date.getSeconds()}`.padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

View File

@@ -18,11 +18,11 @@ export function validatePassword(password: string): {
errors: string[];
} {
const errors: string[] = [];
if (password.length < 8) {
errors.push("Password must be at least 8 characters long");
}
// Optional: Add more password requirements
// if (!/[A-Z]/.test(password)) {
// errors.push("Password must contain at least one uppercase letter");
@@ -33,17 +33,20 @@ export function validatePassword(password: string): {
// if (!/[0-9]/.test(password)) {
// errors.push("Password must contain at least one number");
// }
return {
isValid: errors.length === 0,
errors,
errors
};
}
/**
* Check if two passwords match
*/
export function passwordsMatch(password: string, confirmation: string): boolean {
export function passwordsMatch(
password: string,
confirmation: string
): boolean {
return password === confirmation && password.length > 0;
}
@@ -53,43 +56,3 @@ export function passwordsMatch(password: string, confirmation: string): boolean
export function isValidDisplayName(name: string): boolean {
return name.trim().length >= 1 && name.trim().length <= 50;
}
/**
* Sanitize user input (basic XSS prevention)
*/
export function sanitizeInput(input: string): string {
return input
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#x27;")
.replace(/\//g, "&#x2F;");
}
/**
* Check if string is a valid URL
*/
export function isValidUrl(url: string): boolean {
try {
new URL(url);
return true;
} catch {
return false;
}
}
/**
* Validate file type for uploads
*/
export function isValidImageType(file: File): boolean {
const validTypes = ["image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp"];
return validTypes.includes(file.type);
}
/**
* Validate file size (in bytes)
*/
export function isValidFileSize(file: File, maxSizeMB: number = 5): boolean {
const maxBytes = maxSizeMB * 1024 * 1024;
return file.size <= maxBytes;
}