|
|
@@ -0,0 +1,285 @@
|
|
|
+import React, { useState, useEffect, useCallback, useMemo } from "react"
|
|
|
+import { ComponentType, FC, ReactNode, JSX } from "react"
|
|
|
+
|
|
|
+// Interface definitions
|
|
|
+interface User {
|
|
|
+ id: number
|
|
|
+ name: string
|
|
|
+ email?: string
|
|
|
+ readonly createdAt: Date
|
|
|
+ active: boolean
|
|
|
+}
|
|
|
+
|
|
|
+type Theme = "light" | "dark" | "auto"
|
|
|
+type Status = "pending" | "loading" | "success" | "error"
|
|
|
+
|
|
|
+// Generic function with constraints
|
|
|
+function createRepository<T extends { id: number }>(items: T[]): Repository<T> {
|
|
|
+ return new Repository(items)
|
|
|
+}
|
|
|
+
|
|
|
+// Class definition
|
|
|
+class Repository<T> {
|
|
|
+ private items: T[]
|
|
|
+ protected cache: Map<string, T>
|
|
|
+
|
|
|
+ constructor(items: T[] = []) {
|
|
|
+ this.items = items
|
|
|
+ this.cache = new Map()
|
|
|
+ }
|
|
|
+
|
|
|
+ public find(id: number): T | undefined {
|
|
|
+ return this.items.find((item) => item.id === id)
|
|
|
+ }
|
|
|
+
|
|
|
+ public async findAll(): Promise<T[]> {
|
|
|
+ return this.items
|
|
|
+ }
|
|
|
+
|
|
|
+ get count(): number {
|
|
|
+ return this.items.length
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Enum definition
|
|
|
+enum LogLevel {
|
|
|
+ DEBUG = 0,
|
|
|
+ INFO = 1,
|
|
|
+ WARN = 2,
|
|
|
+ ERROR = 3,
|
|
|
+}
|
|
|
+
|
|
|
+// Constants
|
|
|
+const API_URL = "https://api.example.com"
|
|
|
+const MAX_RETRIES = 3
|
|
|
+const DEFAULT_TIMEOUT = 5000
|
|
|
+
|
|
|
+// Regular expressions
|
|
|
+const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
|
|
+const PHONE_REGEX = /^\+?1?-?\.?\s?\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})$/
|
|
|
+
|
|
|
+// Template literals
|
|
|
+const greeting = `Hello, ${user.name}!`
|
|
|
+const sql = `
|
|
|
+ SELECT * FROM users
|
|
|
+ WHERE active = true
|
|
|
+ AND created_at > '${new Date().toISOString()}'
|
|
|
+`
|
|
|
+
|
|
|
+// Arrow functions
|
|
|
+const debounce = <T extends (...args: any[]) => any>(
|
|
|
+ func: T,
|
|
|
+ wait: number,
|
|
|
+): ((...args: Parameters<T>) => void) => {
|
|
|
+ let timeout: NodeJS.Timeout
|
|
|
+ return (...args: Parameters<T>) => {
|
|
|
+ clearTimeout(timeout)
|
|
|
+ timeout = setTimeout(() => func(...args), wait)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Async function
|
|
|
+async function fetchUserData(userId: number): Promise<User> {
|
|
|
+ try {
|
|
|
+ const response = await fetch(`${API_URL}/users/${userId}`)
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error(`HTTP error! status: ${response.status}`)
|
|
|
+ }
|
|
|
+ return await response.json()
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Failed to fetch user data:", error)
|
|
|
+ throw error
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// React component with various patterns
|
|
|
+const ThemeProvider: FC<{ children: ReactNode; theme?: Theme }> = ({
|
|
|
+ children,
|
|
|
+ theme = "auto",
|
|
|
+}) => {
|
|
|
+ const [currentTheme, setCurrentTheme] = useState<Theme>(theme)
|
|
|
+ const [status, setStatus] = useState<Status>("pending")
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
|
|
|
+ const handleChange = (e: MediaQueryListEvent) => {
|
|
|
+ setCurrentTheme(e.matches ? "dark" : "light")
|
|
|
+ }
|
|
|
+
|
|
|
+ mediaQuery.addEventListener("change", handleChange)
|
|
|
+ return () => mediaQuery.removeEventListener("change", handleChange)
|
|
|
+ }, [])
|
|
|
+
|
|
|
+ const contextValue = useMemo(
|
|
|
+ () => ({
|
|
|
+ theme: currentTheme,
|
|
|
+ setTheme: setCurrentTheme,
|
|
|
+ toggleTheme: () => setCurrentTheme((prev) => (prev === "light" ? "dark" : "light")),
|
|
|
+ }),
|
|
|
+ [currentTheme],
|
|
|
+ )
|
|
|
+
|
|
|
+ return (
|
|
|
+ <ThemeContext.Provider value={contextValue}>
|
|
|
+ <div className={`theme-${currentTheme}`} data-theme={currentTheme}>
|
|
|
+ {children}
|
|
|
+ </div>
|
|
|
+ </ThemeContext.Provider>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+// Higher-order component
|
|
|
+function withLogging<P extends object>(Component: ComponentType<P>): ComponentType<P> {
|
|
|
+ return function LoggedComponent(props: P) {
|
|
|
+ console.log("Rendering component:", Component.name)
|
|
|
+ return <Component {...props} />
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Custom hook
|
|
|
+function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T) => void] {
|
|
|
+ const [storedValue, setStoredValue] = useState<T>(() => {
|
|
|
+ try {
|
|
|
+ const item = window.localStorage.getItem(key)
|
|
|
+ return item ? JSON.parse(item) : initialValue
|
|
|
+ } catch (error) {
|
|
|
+ console.warn(`Error reading localStorage key "${key}":`, error)
|
|
|
+ return initialValue
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const setValue = useCallback(
|
|
|
+ (value: T) => {
|
|
|
+ try {
|
|
|
+ setStoredValue(value)
|
|
|
+ window.localStorage.setItem(key, JSON.stringify(value))
|
|
|
+ } catch (error) {
|
|
|
+ console.warn(`Error setting localStorage key "${key}":`, error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ [key],
|
|
|
+ )
|
|
|
+
|
|
|
+ return [storedValue, setValue]
|
|
|
+}
|
|
|
+
|
|
|
+// JSX component with various elements
|
|
|
+const UserProfile: FC<{ user: User; onUpdate?: (user: User) => void }> = ({ user, onUpdate }) => {
|
|
|
+ const [isEditing, setIsEditing] = useState(false)
|
|
|
+ const [formData, setFormData] = useState(user)
|
|
|
+ const [errors, setErrors] = useState<Record<string, string>>({})
|
|
|
+
|
|
|
+ const handleSubmit = async (e: React.FormEvent) => {
|
|
|
+ e.preventDefault()
|
|
|
+
|
|
|
+ // Validation
|
|
|
+ if (!formData.name.trim()) {
|
|
|
+ setErrors({ name: "Name is required" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (formData.email && !EMAIL_REGEX.test(formData.email)) {
|
|
|
+ setErrors({ email: "Invalid email format" })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ setStatus("loading")
|
|
|
+ await onUpdate?.(formData)
|
|
|
+ setStatus("success")
|
|
|
+ setIsEditing(false)
|
|
|
+ } catch (error) {
|
|
|
+ setStatus("error")
|
|
|
+ setErrors({ submit: "Failed to update profile" })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="user-profile">
|
|
|
+ <div className="user-header">
|
|
|
+ <h2>{user.name}</h2>
|
|
|
+ <span className={`status status-${user.active ? "active" : "inactive"}`}>
|
|
|
+ {user.active ? "Active" : "Inactive"}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {isEditing ? (
|
|
|
+ <form onSubmit={handleSubmit} className="user-form">
|
|
|
+ <div className="form-group">
|
|
|
+ <label htmlFor="name">Name:</label>
|
|
|
+ <input
|
|
|
+ id="name"
|
|
|
+ type="text"
|
|
|
+ value={formData.name}
|
|
|
+ onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
|
+ className={errors.name ? "error" : ""}
|
|
|
+ placeholder="Enter your name"
|
|
|
+ required
|
|
|
+ />
|
|
|
+ {errors.name && <span className="error-message">{errors.name}</span>}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="form-group">
|
|
|
+ <label htmlFor="email">Email:</label>
|
|
|
+ <input
|
|
|
+ id="email"
|
|
|
+ type="email"
|
|
|
+ value={formData.email || ""}
|
|
|
+ onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
|
+ className={errors.email ? "error" : ""}
|
|
|
+ placeholder="[email protected]"
|
|
|
+ />
|
|
|
+ {errors.email && <span className="error-message">{errors.email}</span>}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="form-actions">
|
|
|
+ <button type="submit" disabled={status === "loading"}>
|
|
|
+ {status === "loading" ? "Saving..." : "Save"}
|
|
|
+ </button>
|
|
|
+ <button type="button" onClick={() => setIsEditing(false)} className="secondary">
|
|
|
+ Cancel
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {errors.submit && <div className="alert alert-error">{errors.submit}</div>}
|
|
|
+ </form>
|
|
|
+ ) : (
|
|
|
+ <div className="user-details">
|
|
|
+ <p>
|
|
|
+ <strong>ID:</strong> {user.id}
|
|
|
+ </p>
|
|
|
+ <p>
|
|
|
+ <strong>Email:</strong> {user.email || "Not provided"}
|
|
|
+ </p>
|
|
|
+ <p>
|
|
|
+ <strong>Member since:</strong> {user.createdAt.toLocaleDateString()}
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <button onClick={() => setIsEditing(true)} className="edit-button">
|
|
|
+ Edit Profile
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+// Export statements
|
|
|
+export {
|
|
|
+ User,
|
|
|
+ Theme,
|
|
|
+ Status,
|
|
|
+ LogLevel,
|
|
|
+ Repository,
|
|
|
+ ThemeProvider,
|
|
|
+ UserProfile,
|
|
|
+ fetchUserData,
|
|
|
+ useLocalStorage,
|
|
|
+ withLogging,
|
|
|
+ debounce,
|
|
|
+}
|
|
|
+
|
|
|
+export default ThemeProvider
|
|
|
+
|
|
|
+// Type exports
|
|
|
+export type { User as UserType, ComponentType as ReactComponentType }
|