Add API endpoints and frontend components for tool management and analytics

Implement CRUD operations for tools and ratings, introduce analytics endpoints, and develop frontend components for displaying tools, ratings, and analytics data.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 776963d0-f75d-42e2-a57b-cc36bdff8495
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: feaa4ce1-5aed-4cc0-bcea-47855b615b48
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0683fb79-a27c-485c-9333-5f4b288c4567/776963d0-f75d-42e2-a57b-cc36bdff8495/rx9K7bW
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
cheffe01
2026-05-25 13:04:53 +00:00
parent 1de22a6979
commit 036973ea32
111 changed files with 11006 additions and 96 deletions
+260 -5
View File
@@ -1,16 +1,271 @@
/**
* Generated by orval v8.5.3 🍺
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* API specification
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
import * as zod from "zod";
import * as zod from 'zod';
/**
* Returns server health status
* @summary Health check
*/
export const HealthCheckResponse = zod.object({
status: zod.string(),
});
"status": zod.string()
})
/**
* @summary List all tools
*/
export const ListToolsQueryParams = zod.object({
"category": zod.coerce.string().optional(),
"search": zod.coerce.string().optional(),
"sort": zod.enum(['newest', 'top_rated', 'most_reviewed']).optional()
})
export const ListToolsResponseItem = zod.object({
"id": zod.number(),
"name": zod.string(),
"description": zod.string(),
"category": zod.string(),
"websiteUrl": zod.string().nullish(),
"features": zod.array(zod.string()).optional(),
"tags": zod.array(zod.string()).optional(),
"createdAt": zod.coerce.date(),
"updatedAt": zod.coerce.date(),
"ratingCount": zod.number(),
"avgUsefulness": zod.number().nullable(),
"avgUsability": zod.number().nullable(),
"avgCombined": zod.number().nullable()
})
export const ListToolsResponse = zod.array(ListToolsResponseItem)
/**
* @summary Create a new tool
*/
export const CreateToolBody = zod.object({
"name": zod.string().min(1),
"description": zod.string().min(1),
"category": zod.string().min(1),
"websiteUrl": zod.string().optional(),
"features": zod.array(zod.string()).optional(),
"tags": zod.array(zod.string()).optional()
})
/**
* @summary Get a tool by ID
*/
export const GetToolParams = zod.object({
"id": zod.coerce.number()
})
export const GetToolResponse = zod.object({
"id": zod.number(),
"name": zod.string(),
"description": zod.string(),
"category": zod.string(),
"websiteUrl": zod.string().nullish(),
"features": zod.array(zod.string()).optional(),
"tags": zod.array(zod.string()).optional(),
"createdAt": zod.coerce.date(),
"updatedAt": zod.coerce.date(),
"ratingCount": zod.number(),
"avgUsefulness": zod.number().nullable(),
"avgUsability": zod.number().nullable(),
"avgCombined": zod.number().nullable()
})
/**
* @summary Update a tool
*/
export const UpdateToolParams = zod.object({
"id": zod.coerce.number()
})
export const UpdateToolBody = zod.object({
"name": zod.string().min(1).optional(),
"description": zod.string().optional(),
"category": zod.string().optional(),
"websiteUrl": zod.string().optional(),
"features": zod.array(zod.string()).optional(),
"tags": zod.array(zod.string()).optional()
})
export const UpdateToolResponse = zod.object({
"id": zod.number(),
"name": zod.string(),
"description": zod.string(),
"category": zod.string(),
"websiteUrl": zod.string().nullish(),
"features": zod.array(zod.string()).optional(),
"tags": zod.array(zod.string()).optional(),
"createdAt": zod.coerce.date(),
"updatedAt": zod.coerce.date()
})
/**
* @summary Delete a tool
*/
export const DeleteToolParams = zod.object({
"id": zod.coerce.number()
})
/**
* @summary List ratings for a tool
*/
export const ListToolRatingsParams = zod.object({
"id": zod.coerce.number()
})
export const listToolRatingsResponseUsefulnessMax = 5;
export const listToolRatingsResponseUsabilityMax = 5;
export const ListToolRatingsResponseItem = zod.object({
"id": zod.number(),
"toolId": zod.number(),
"usefulness": zod.number().min(1).max(listToolRatingsResponseUsefulnessMax),
"usability": zod.number().min(1).max(listToolRatingsResponseUsabilityMax),
"comment": zod.string().nullish(),
"reviewerName": zod.string().nullish(),
"createdAt": zod.coerce.date()
})
export const ListToolRatingsResponse = zod.array(ListToolRatingsResponseItem)
/**
* @summary Submit a rating for a tool
*/
export const CreateRatingParams = zod.object({
"id": zod.coerce.number()
})
export const createRatingBodyUsefulnessMax = 5;
export const createRatingBodyUsabilityMax = 5;
export const CreateRatingBody = zod.object({
"usefulness": zod.number().min(1).max(createRatingBodyUsefulnessMax),
"usability": zod.number().min(1).max(createRatingBodyUsabilityMax),
"comment": zod.string().optional(),
"reviewerName": zod.string().optional()
})
/**
* @summary Overall platform statistics
*/
export const GetAnalyticsSummaryResponse = zod.object({
"totalTools": zod.number(),
"totalRatings": zod.number(),
"avgUsefulness": zod.number().nullable(),
"avgUsability": zod.number().nullable(),
"avgCombined": zod.number().nullable(),
"categoriesCount": zod.number(),
"mostRatedTool": zod.object({
"id": zod.number(),
"name": zod.string(),
"description": zod.string(),
"category": zod.string(),
"websiteUrl": zod.string().nullish(),
"features": zod.array(zod.string()).optional(),
"tags": zod.array(zod.string()).optional(),
"createdAt": zod.coerce.date(),
"updatedAt": zod.coerce.date(),
"ratingCount": zod.number(),
"avgUsefulness": zod.number().nullable(),
"avgUsability": zod.number().nullable(),
"avgCombined": zod.number().nullable()
}).optional()
})
/**
* @summary Top-rated tools
*/
export const GetTopToolsQueryParams = zod.object({
"limit": zod.coerce.number().optional(),
"metric": zod.enum(['usefulness', 'usability', 'combined']).optional()
})
export const GetTopToolsResponseItem = zod.object({
"tool": zod.object({
"id": zod.number(),
"name": zod.string(),
"description": zod.string(),
"category": zod.string(),
"websiteUrl": zod.string().nullish(),
"features": zod.array(zod.string()).optional(),
"tags": zod.array(zod.string()).optional(),
"createdAt": zod.coerce.date(),
"updatedAt": zod.coerce.date(),
"ratingCount": zod.number(),
"avgUsefulness": zod.number().nullable(),
"avgUsability": zod.number().nullable(),
"avgCombined": zod.number().nullable()
}),
"score": zod.number(),
"ratingCount": zod.number()
})
export const GetTopToolsResponse = zod.array(GetTopToolsResponseItem)
/**
* @summary Rating statistics grouped by category
*/
export const GetAnalyticsByCategoryResponseItem = zod.object({
"category": zod.string(),
"toolCount": zod.number(),
"totalRatings": zod.number(),
"avgUsefulness": zod.number().nullable(),
"avgUsability": zod.number().nullable()
})
export const GetAnalyticsByCategoryResponse = zod.array(GetAnalyticsByCategoryResponseItem)
/**
* @summary Distribution of rating scores across the platform
*/
export const GetRatingDistributionQueryParams = zod.object({
"toolId": zod.coerce.number().optional()
})
export const GetRatingDistributionResponse = zod.object({
"usefulness": zod.array(zod.object({
"score": zod.number(),
"count": zod.number()
})),
"usability": zod.array(zod.object({
"score": zod.number(),
"count": zod.number()
}))
})
/**
* @summary List all distinct tool categories
*/
export const ListCategoriesResponseItem = zod.string()
export const ListCategoriesResponse = zod.array(ListCategoriesResponseItem)
@@ -0,0 +1,21 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
import type { ToolWithStats } from './toolWithStats';
export interface AnalyticsSummary {
totalTools: number;
totalRatings: number;
/** @nullable */
avgUsefulness: number | null;
/** @nullable */
avgUsability: number | null;
/** @nullable */
avgCombined: number | null;
categoriesCount: number;
mostRatedTool?: ToolWithStats;
}
@@ -0,0 +1,17 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface CategoryStats {
category: string;
toolCount: number;
totalRatings: number;
/** @nullable */
avgUsefulness: number | null;
/** @nullable */
avgUsability: number | null;
}
@@ -0,0 +1,11 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface ErrorResponse {
error: string;
}
@@ -0,0 +1,11 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export type GetRatingDistributionParams = {
toolId?: number;
};
@@ -0,0 +1,16 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export type GetTopToolsMetric = typeof GetTopToolsMetric[keyof typeof GetTopToolsMetric];
export const GetTopToolsMetric = {
usefulness: 'usefulness',
usability: 'usability',
combined: 'combined',
} as const;
@@ -0,0 +1,13 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
import type { GetTopToolsMetric } from './getTopToolsMetric';
export type GetTopToolsParams = {
limit?: number;
metric?: GetTopToolsMetric;
};
@@ -1,8 +1,8 @@
/**
* Generated by orval v8.5.3 🍺
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* API specification
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
+20 -3
View File
@@ -1,9 +1,26 @@
/**
* Generated by orval v8.5.3 🍺
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* API specification
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export * from "./healthStatus";
export * from './analyticsSummary';
export * from './categoryStats';
export * from './errorResponse';
export * from './getRatingDistributionParams';
export * from './getTopToolsMetric';
export * from './getTopToolsParams';
export * from './healthStatus';
export * from './listToolsParams';
export * from './listToolsSort';
export * from './rating';
export * from './ratingDistribution';
export * from './ratingInput';
export * from './scoreBucket';
export * from './tool';
export * from './toolInput';
export * from './toolUpdate';
export * from './toolWithStats';
export * from './topToolEntry';
@@ -0,0 +1,14 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
import type { ListToolsSort } from './listToolsSort';
export type ListToolsParams = {
category?: string;
search?: string;
sort?: ListToolsSort;
};
@@ -0,0 +1,16 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export type ListToolsSort = typeof ListToolsSort[keyof typeof ListToolsSort];
export const ListToolsSort = {
newest: 'newest',
top_rated: 'top_rated',
most_reviewed: 'most_reviewed',
} as const;
+27
View File
@@ -0,0 +1,27 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface Rating {
id: number;
toolId: number;
/**
* @minimum 1
* @maximum 5
*/
usefulness: number;
/**
* @minimum 1
* @maximum 5
*/
usability: number;
/** @nullable */
comment?: string | null;
/** @nullable */
reviewerName?: string | null;
createdAt: Date;
}
@@ -0,0 +1,13 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
import type { ScoreBucket } from './scoreBucket';
export interface RatingDistribution {
usefulness: ScoreBucket[];
usability: ScoreBucket[];
}
@@ -0,0 +1,22 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface RatingInput {
/**
* @minimum 1
* @maximum 5
*/
usefulness: number;
/**
* @minimum 1
* @maximum 5
*/
usability: number;
comment?: string;
reviewerName?: string;
}
@@ -0,0 +1,12 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface ScoreBucket {
score: number;
count: number;
}
+20
View File
@@ -0,0 +1,20 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface Tool {
id: number;
name: string;
description: string;
category: string;
/** @nullable */
websiteUrl?: string | null;
features?: string[];
tags?: string[];
createdAt: Date;
updatedAt: Date;
}
@@ -0,0 +1,19 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface ToolInput {
/** @minLength 1 */
name: string;
/** @minLength 1 */
description: string;
/** @minLength 1 */
category: string;
websiteUrl?: string;
features?: string[];
tags?: string[];
}
@@ -0,0 +1,17 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface ToolUpdate {
/** @minLength 1 */
name?: string;
description?: string;
category?: string;
websiteUrl?: string;
features?: string[];
tags?: string[];
}
@@ -0,0 +1,27 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
export interface ToolWithStats {
id: number;
name: string;
description: string;
category: string;
/** @nullable */
websiteUrl?: string | null;
features?: string[];
tags?: string[];
createdAt: Date;
updatedAt: Date;
ratingCount: number;
/** @nullable */
avgUsefulness: number | null;
/** @nullable */
avgUsability: number | null;
/** @nullable */
avgCombined: number | null;
}
@@ -0,0 +1,14 @@
/**
* Generated by orval v8.9.1 🍺
* Do not edit manually.
* Api
* ToolRate API — Tool listing and rating platform
* OpenAPI spec version: 0.1.0
*/
import type { ToolWithStats } from './toolWithStats';
export interface TopToolEntry {
tool: ToolWithStats;
score: number;
ratingCount: number;
}