feat: complete development environment setup and code quality improvements

- Set up pre-commit hooks with husky and lint-staged for automated code quality
- Improved TypeScript type safety by replacing 'any' types with proper generics
- Fixed markdown linting violations (MD030 spacing) across all documentation
- Fixed compound adjective hyphenation in technical documentation
- Fixed invalid JSON union syntax in API documentation examples
- Automated code formatting and linting on commit
- Enhanced error handling with better type constraints
- Configured biome and markdownlint for consistent code style
- All changes verified with successful production build
This commit is contained in:
2025-07-13 14:44:05 +02:00
parent 1d4e695e41
commit e2301725a3
54 changed files with 2335 additions and 1863 deletions

View File

@ -232,14 +232,14 @@ function useCompanyData(
} else {
const errorText = await response.text();
const errorMessage = `Failed to load company data (${response.status}: ${response.statusText})`;
console.error("Failed to fetch company - HTTP Error:", {
status: response.status,
statusText: response.statusText,
response: errorText,
url: response.url,
});
toast({
title: "Error",
description: errorMessage,
@ -247,17 +247,18 @@ function useCompanyData(
});
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
const errorMessage =
error instanceof Error ? error.message : "Unknown error occurred";
console.error("Failed to fetch company - Network/Parse Error:", {
message: errorMessage,
error: error,
stack: error instanceof Error ? error.stack : undefined,
url: `/api/platform/companies/${params.id}`,
});
toast({
title: "Error",
title: "Error",
description: `Failed to load company data: ${errorMessage}`,
variant: "destructive",
});
@ -371,12 +372,13 @@ function renderCompanyInfoCard(
onChange={(e) => {
const value = e.target.value;
const parsedValue = Number.parseInt(value, 10);
// Validate input: must be a positive number
const maxUsers = !Number.isNaN(parsedValue) && parsedValue > 0
? parsedValue
: 1; // Default to 1 for invalid/negative values
const maxUsers =
!Number.isNaN(parsedValue) && parsedValue > 0
? parsedValue
: 1; // Default to 1 for invalid/negative values
state.setEditData((prev) => ({
...prev,
maxUsers,

View File

@ -156,7 +156,9 @@ function usePlatformDashboardState() {
adminPassword: "",
maxUsers: 10,
});
const [validationErrors, setValidationErrors] = useState<ValidationErrors>({});
const [validationErrors, setValidationErrors] = useState<ValidationErrors>(
{}
);
return {
dashboardData,
@ -210,22 +212,23 @@ function useFormIds() {
*/
function validateEmail(email: string): string | undefined {
if (!email) return undefined;
const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
const emailRegex =
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
if (!emailRegex.test(email)) {
return "Please enter a valid email address";
}
return undefined;
}
function validateUrl(url: string): string | undefined {
if (!url) return undefined;
try {
const urlObj = new URL(url);
if (!['http:', 'https:'].includes(urlObj.protocol)) {
if (!["http:", "https:"].includes(urlObj.protocol)) {
return "URL must use HTTP or HTTPS protocol";
}
return undefined;
@ -271,7 +274,7 @@ function renderCompanyFormFields(
...prev,
csvUrl: value,
}));
// Validate URL on change
const error = validateUrl(value);
setValidationErrors((prev) => ({
@ -341,7 +344,7 @@ function renderCompanyFormFields(
...prev,
adminEmail: value,
}));
// Validate email on change
const error = validateEmail(value);
setValidationErrors((prev) => ({
@ -683,13 +686,12 @@ export default function PlatformDashboard() {
newCompanyData.adminEmail &&
newCompanyData.adminName
);
// Check for validation errors
const hasValidationErrors = !!(
validationErrors.csvUrl ||
validationErrors.adminEmail
validationErrors.csvUrl || validationErrors.adminEmail
);
return hasRequiredFields && !hasValidationErrors;
};