layout improvements

This commit is contained in:
overcuriousity 2025-07-24 19:18:41 +02:00
parent f92219f61f
commit f76999ed2e
2 changed files with 275 additions and 96 deletions

View File

@ -39,108 +39,130 @@ const { authenticated, userEmail, userId } = authResult;
</div> </div>
<!-- Contribution Options --> <!-- Contribution Options -->
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 2rem; margin-bottom: 3rem;"> <!-- WRAPPER -->
<div
style="
display:grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap:2rem;
align-items:stretch;
margin-bottom: 2rem;
"
>
<!-- Tools, Methods & Concepts --> <!-- Tools, Methods & Concepts -->
<div class="card" style="padding: 2rem; border-left: 4px solid var(--color-primary); cursor: pointer; transition: var(--transition-fast);" onclick="window.location.href='/contribute/tool'"> <div class="card"
<div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem;"> style="padding: 2rem; border-left: 4px solid var(--color-primary); cursor: pointer; transition: var(--transition-fast);
<div style="width: 48px; height: 48px; background-color: var(--color-primary); border-radius: 0.5rem; display: flex; align-items: center; justify-content: center;"> display:flex; flex-direction:column;"
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"> onclick="window.location.href='/contribute/tool'">
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/> <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem;">
</svg> <div style="width: 48px; height: 48px; background-color: var(--color-primary); border-radius: 0.5rem; display: flex; align-items: center; justify-content: center;">
</div> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<h3 style="margin: 0; color: var(--color-primary); font-size: 1.25rem;">Tools, Methods & Concepts</h3> <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>
</div> </svg>
</div>
<h3 style="margin: 0; color: var(--color-primary); font-size: 1.25rem;">Tools, Methods & Concepts</h3>
</div>
<p style="margin-bottom: 1.5rem; line-height: 1.6;"> <p style="margin-bottom: 1.5rem; line-height: 1.6;">
Add new software tools, forensic methodologies, or fundamental concepts to our database. Add new software tools, forensic methodologies, or fundamental concepts to our database.
Includes detailed forms for metadata, licensing, platforms, and categorization. Includes detailed forms for metadata, licensing, platforms, and categorization.
</p>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.5rem;">
<span class="badge" style="background-color: var(--color-primary); color: white;">Software Tools</span>
<span class="badge" style="background-color: var(--color-method); color: white;">Methods</span>
<span class="badge" style="background-color: var(--color-concept); color: white;">Concepts</span>
</div>
<div style="margin-top:auto; display:flex; gap:1rem;">
<a href="/contribute/tool" class="btn btn-primary" style="flex: 1;">Add New Entry</a>
<a href="/contribute/tool?mode=browse" class="btn btn-secondary" style="flex: 1;">Edit Existing</a>
</div>
</div>
<!-- Knowledgebase Articles -->
<div class="card"
style="padding: 2rem; border-left: 4px solid var(--color-accent); cursor: pointer; transition: var(--transition-fast);
display:flex; flex-direction:column;"
onclick="window.location.href='/contribute/knowledgebase'">
<div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem;">
<div style="width: 48px; height: 48px; background-color: var(--color-accent); border-radius: 0.5rem; display: flex; align-items: center; justify-content: center;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
<line x1="16" y1="13" x2="8" y2="13"/>
<line x1="16" y1="17" x2="8" y2="17"/>
<polyline points="10 9 9 9 8 9"/>
</svg>
</div>
<h3 style="margin: 0; color: var(--color-accent); font-size: 1.25rem;">Knowledgebase Articles</h3>
</div>
<p style="margin-bottom: 1.5rem; line-height: 1.6;">
Write detailed guides, tutorials, configuration instructions, and best practices.
Features a markdown editor with live preview and media upload capabilities.
</p>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.5rem;">
<span class="badge badge-secondary">Installation Guides</span>
<span class="badge badge-secondary">Tutorials</span>
<span class="badge badge-secondary">Best Practices</span>
<span class="badge badge-secondary">Case Studies</span>
</div>
<div style="margin-top:auto; display:flex; gap:1rem;">
<a href="/contribute/knowledgebase" class="btn btn-accent" style="flex: 1;">Write Article</a>
<a href="/knowledgebase" class="btn btn-secondary" style="flex: 1;">View Articles</a>
</div>
</div>
<!-- Issues & Improvements -->
<div class="card"
style="padding: 2rem; border-left: 4px solid var(--color-accent); cursor: pointer; transition: var(--transition-fast);
display:flex; flex-direction:column;">
<div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem;">
<div style="width: 48px; height: 48px; background-color: var(--color-warning); border-radius: 0.5rem; display: flex; align-items: center; justify-content: center;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<line x1="12" y1="8" x2="12" y2="12"/>
<line x1="12" y1="16" x2="12.01" y2="16"/>
</svg>
</div>
<h3 style="margin: 0; color: var(--color-warning); font-size: 1.25rem;">Issues & Improvements</h3>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 2rem; align-items: center;">
<div style="display:flex; flex-direction:column;">
<p style="margin-bottom: 1rem; line-height: 1.6;">
Found incorrect information, broken links, or have suggestions for improvements?
Report issues directly in our Git repository or suggest enhancements to existing entries.
</p> </p>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.5rem;"> <span class="badge" style="background-color: var(--color-warning); color: white;">Bug Reports</span>
<span class="badge" style="background-color: var(--color-primary); color: white;">Software Tools</span> <span class="badge" style="background-color: var(--color-warning); color: white;">Corrections</span>
<span class="badge" style="background-color: var(--color-method); color: white;">Methods</span> <span class="badge" style="background-color: var(--color-warning); color: white;">Suggestions</span>
<span class="badge" style="background-color: var(--color-concept); color: white;">Concepts</span>
</div>
<div style="display: flex; gap: 1rem;">
<a href="/contribute/tool" class="btn btn-primary" style="flex: 1;">Add New Entry</a>
<a href="/contribute/tool?mode=browse" class="btn btn-secondary" style="flex: 1;">Edit Existing</a>
</div> </div>
</div> </div>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<!-- Knowledgebase Articles --> <a href="https://git.cc24.dev/mstoeck3/cc24-hub/issues/new" target="_blank" rel="noopener noreferrer" class="btn" style="background-color: var(--color-warning); color: white; border-color: var(--color-warning);">
<div class="card" style="padding: 2rem; border-left: 4px solid var(--color-accent); cursor: pointer; transition: var(--transition-fast);" onclick="window.location.href='/contribute/knowledgebase'"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem;"> <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<div style="width: 48px; height: 48px; background-color: var(--color-accent); border-radius: 0.5rem; display: flex; align-items: center; justify-content: center;"> <polyline points="15 3 21 3 21 9"/>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"> <line x1="10" y1="14" x2="21" y2="3"/>
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/> </svg>
<polyline points="14 2 14 8 20 8"/> Report Issue
<line x1="16" y1="13" x2="8" y2="13"/> </a>
<line x1="16" y1="17" x2="8" y2="17"/>
<polyline points="10 9 9 9 8 9"/>
</svg>
</div>
<h3 style="margin: 0; color: var(--color-accent); font-size: 1.25rem;">Knowledgebase Articles</h3>
</div>
<p style="margin-bottom: 1.5rem; line-height: 1.6;">
Write detailed guides, tutorials, configuration instructions, and best practices.
Features a markdown editor with live preview and media upload capabilities.
</p>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.5rem;">
<span class="badge badge-secondary">Installation Guides</span>
<span class="badge badge-secondary">Tutorials</span>
<span class="badge badge-secondary">Best Practices</span>
<span class="badge badge-secondary">Case Studies</span>
</div>
<div style="display: flex; gap: 1rem;">
<a href="/contribute/knowledgebase" class="btn btn-accent" style="flex: 1;">Write Article</a>
<a href="/knowledgebase" class="btn btn-secondary" style="flex: 1;">View Articles</a>
</div>
</div>
<!-- Issues & Improvements -->
<div class="card" style="padding: 2rem; border-left: 4px solid var(--color-warning); grid-column: 1 / -1;">
<div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem;">
<div style="width: 48px; height: 48px; background-color: var(--color-warning); border-radius: 0.5rem; display: flex; align-items: center; justify-content: center;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<line x1="12" y1="8" x2="12" y2="12"/>
<line x1="12" y1="16" x2="12.01" y2="16"/>
</svg>
</div>
<h3 style="margin: 0; color: var(--color-warning); font-size: 1.25rem;">Issues & Improvements</h3>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 2rem; align-items: center;">
<div>
<p style="margin-bottom: 1rem; line-height: 1.6;">
Found incorrect information, broken links, or have suggestions for improvements?
Report issues directly in our Git repository or suggest enhancements to existing entries.
</p>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
<span class="badge" style="background-color: var(--color-warning); color: white;">Bug Reports</span>
<span class="badge" style="background-color: var(--color-warning); color: white;">Corrections</span>
<span class="badge" style="background-color: var(--color-warning); color: white;">Suggestions</span>
</div>
</div>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<a href="https://git.cc24.dev/mstoeck3/cc24-hub/issues/new" target="_blank" rel="noopener noreferrer" class="btn" style="background-color: var(--color-warning); color: white; border-color: var(--color-warning);">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" y1="14" x2="21" y2="3"/>
</svg>
Report Issue
</a>
</div>
</div>
</div> </div>
</div> </div>
<!-- Push this actions block down if you add more later -->
<div style="margin-top:auto;"></div>
</div>
</div>
<!-- Guidelines --> <!-- Guidelines -->
<div class="card" style="margin-bottom: 2rem;"> <div class="card" style="margin-bottom: 2rem;">
<h3 style="margin-bottom: 1.5rem; color: var(--color-text);">Contribution Guidelines</h3> <h3 style="margin-bottom: 1.5rem; color: var(--color-text);">Contribution Guidelines</h3>

157
src/utils/api.ts Normal file
View File

@ -0,0 +1,157 @@
// src/utils/api.ts
// Standard JSON headers for all API responses
const JSON_HEADERS = {
'Content-Type': 'application/json'
} as const;
/**
* Base function to create consistent API responses
* All other response helpers use this internally
*/
export function createAPIResponse(data: any, status: number = 200, additionalHeaders?: Record<string, string>): Response {
const headers = additionalHeaders
? { ...JSON_HEADERS, ...additionalHeaders }
: JSON_HEADERS;
return new Response(JSON.stringify(data), {
status,
headers
});
}
/**
* Success responses (2xx status codes)
*/
export const apiResponse = {
// 200 - Success with data
success: (data: any = { success: true }): Response =>
createAPIResponse(data, 200),
// 201 - Created (for contribution submissions, uploads, etc.)
created: (data: any = { success: true }): Response =>
createAPIResponse(data, 201),
// 202 - Accepted (for async operations)
accepted: (data: any = { success: true, message: 'Request accepted for processing' }): Response =>
createAPIResponse(data, 202)
};
/**
* Client error responses (4xx status codes)
*/
export const apiError = {
// 400 - Bad Request
badRequest: (message: string = 'Bad request', details?: string[]): Response =>
createAPIResponse({
success: false,
error: message,
...(details && { details })
}, 400),
// 401 - Unauthorized
unauthorized: (message: string = 'Authentication required'): Response =>
createAPIResponse({ success: false, error: message }, 401),
// 403 - Forbidden
forbidden: (message: string = 'Access denied'): Response =>
createAPIResponse({ success: false, error: message }, 403),
// 404 - Not Found
notFound: (message: string = 'Resource not found'): Response =>
createAPIResponse({ success: false, error: message }, 404),
// 422 - Unprocessable Entity (validation errors)
validation: (message: string = 'Validation failed', details?: string[]): Response =>
createAPIResponse({
success: false,
error: message,
...(details && { details })
}, 422),
// 429 - Rate Limited
rateLimit: (message: string = 'Rate limit exceeded. Please wait before trying again.'): Response =>
createAPIResponse({ success: false, error: message }, 429)
};
/**
* Server error responses (5xx status codes)
*/
export const apiServerError = {
// 500 - Internal Server Error
internal: (message: string = 'Internal server error'): Response =>
createAPIResponse({ success: false, error: message }, 500),
// 502 - Bad Gateway (external service issues)
badGateway: (message: string = 'External service error'): Response =>
createAPIResponse({ success: false, error: message }, 502),
// 503 - Service Unavailable
unavailable: (message: string = 'Service temporarily unavailable'): Response =>
createAPIResponse({ success: false, error: message }, 503),
// 504 - Gateway Timeout
timeout: (message: string = 'Request timeout'): Response =>
createAPIResponse({ success: false, error: message }, 504)
};
/**
* Specialized response helpers for common patterns
*/
export const apiSpecial = {
// JSON parsing error
invalidJSON: (): Response =>
apiError.badRequest('Invalid JSON in request body'),
// Missing required fields
missingRequired: (fields: string[]): Response =>
apiError.badRequest(`Missing required fields: ${fields.join(', ')}`),
// Empty request body
emptyBody: (): Response =>
apiError.badRequest('Request body cannot be empty'),
// File upload responses
uploadSuccess: (data: { url: string; filename: string; size: number; storage: string }): Response =>
apiResponse.created(data),
uploadFailed: (error: string): Response =>
apiServerError.internal(`Upload failed: ${error}`),
// Contribution responses
contributionSuccess: (data: { prUrl?: string; branchName?: string; message: string }): Response =>
apiResponse.created({ success: true, ...data }),
contributionFailed: (error: string): Response =>
apiServerError.internal(`Contribution failed: ${error}`)
};
export const apiWithHeaders = {
// Success with custom headers (e.g., Set-Cookie)
successWithHeaders: (data: any, headers: Record<string, string>): Response =>
createAPIResponse(data, 200, headers),
// Redirect response
redirect: (location: string, temporary: boolean = true): Response =>
new Response(null, {
status: temporary ? 302 : 301,
headers: { 'Location': location }
})
};
export async function handleAPIRequest<T>(
operation: () => Promise<T>,
errorMessage: string = 'Request processing failed'
): Promise<T | Response> {
try {
return await operation();
} catch (error) {
console.error(`API Error: ${errorMessage}:`, error);
return apiServerError.internal(errorMessage);
}
}
export const createAuthErrorResponse = apiError.unauthorized;
export const createBadRequestResponse = apiError.badRequest;
export const createSuccessResponse = apiResponse.success;