feat: add UI components including Skeleton, Slider, Toaster, Switch, Table, Tabs, Textarea, Toggle Group, Toggle, Tooltip, and User Avatar
- Implemented Skeleton component for loading states. - Added Slider component using Radix UI for customizable sliders. - Created Toaster component for notifications with theme support. - Developed Switch component for toggle functionality. - Introduced Table component with subcomponents for structured data display. - Built Tabs component for tabbed navigation. - Added Textarea component for multi-line text input. - Implemented Toggle Group and Toggle components for grouped toggle buttons. - Created Tooltip component for displaying additional information on hover. - Added User Avatar component for displaying user images with fallback. - Implemented useIsMobile hook for responsive design. - Created API utility functions for user and thought data fetching. - Added utility function for class name merging. - Updated package.json with new dependencies for UI components and utilities. - Added TypeScript configuration for path aliasing.
This commit is contained in:
59
thoughts-frontend/lib/api.ts
Normal file
59
thoughts-frontend/lib/api.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const UserSchema = z.object({
|
||||
id: z.uuid(),
|
||||
username: z.string(),
|
||||
displayName: z.string().nullable(),
|
||||
bio: z.string().nullable(),
|
||||
avatarUrl: z.url().nullable(),
|
||||
headerUrl: z.url().nullable(),
|
||||
customCss: z.string().nullable(),
|
||||
topFriends: z.array(z.string()),
|
||||
joinedAt: z.coerce.date(),
|
||||
});
|
||||
|
||||
export const ThoughtSchema = z.object({
|
||||
id: z.uuid(),
|
||||
authorUsername: z.string(),
|
||||
content: z.string(),
|
||||
visibility: z.enum(["Public", "FriendsOnly", "Private"]),
|
||||
replyToId: z.uuid().nullable(),
|
||||
createdAt: z.string().datetime(),
|
||||
});
|
||||
|
||||
export type User = z.infer<typeof UserSchema>;
|
||||
export type Thought = z.infer<typeof ThoughtSchema>;
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";
|
||||
|
||||
async function apiFetch<T>(
|
||||
endpoint: string,
|
||||
options: RequestInit = {},
|
||||
schema: z.ZodType<T>
|
||||
): Promise<T> {
|
||||
const response = await fetch(`${API_BASE_URL}${endpoint}`, {
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...options.headers,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`API request failed with status ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return schema.parse(data);
|
||||
}
|
||||
|
||||
// --- User API Functions ---
|
||||
export const getUserProfile = (username: string) =>
|
||||
apiFetch(`/users/${username}`, {}, UserSchema);
|
||||
|
||||
export const getUserThoughts = (username: string) =>
|
||||
apiFetch(
|
||||
`/users/${username}/thoughts`,
|
||||
{},
|
||||
z.object({ thoughts: z.array(ThoughtSchema) })
|
||||
);
|
6
thoughts-frontend/lib/utils.ts
Normal file
6
thoughts-frontend/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
Reference in New Issue
Block a user