diff --git a/package.json b/package.json new file mode 100644 index 0000000..5dec6bb --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "test-fixes", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "next": "^14.2.0", + "react": "^18.3.0", + "react-dom": "^18.3.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "typescript": "^5.4.0", + "tailwindcss": "^3.4.0", + "postcss": "^8.4.0", + "autoprefixer": "^10.4.0" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx new file mode 100644 index 0000000..6100f74 --- /dev/null +++ b/src/app/settings/page.tsx @@ -0,0 +1,10 @@ +import SettingsPage from '../../components/SettingsPage'; + +export const metadata = { + title: 'Settings', + description: 'Manage your account settings and preferences.', +}; + +export default function SettingsRoute() { + return ; +} diff --git a/src/components/SettingsPage.tsx b/src/components/SettingsPage.tsx new file mode 100644 index 0000000..d9f69fd --- /dev/null +++ b/src/components/SettingsPage.tsx @@ -0,0 +1,554 @@ +'use client'; + +import React, { useState, useCallback } from 'react'; +import ToggleSwitch from './ToggleSwitch'; +import type { + ProfileSettings, + SecuritySettings, + NotificationSettings, + SettingsTab, +} from '../types/settings'; + +/* ────────────────────────── Tab Button ────────────────────────── */ + +interface TabButtonProps { + tab: SettingsTab; + activeTab: SettingsTab; + label: string; + icon: React.ReactNode; + onClick: (tab: SettingsTab) => void; +} + +const TabButton: React.FC = ({ + tab, + activeTab, + label, + icon, + onClick, +}) => { + const isActive = tab === activeTab; + return ( + + ); +}; + +/* ────────────────────────── Form Input ────────────────────────── */ + +interface FormInputProps { + id: string; + label: string; + type?: string; + value: string; + onChange: (value: string) => void; + placeholder?: string; + disabled?: boolean; +} + +const FormInput: React.FC = ({ + id, + label, + type = 'text', + value, + onChange, + placeholder, + disabled = false, +}) => ( +
+ + onChange(e.target.value)} + placeholder={placeholder} + disabled={disabled} + className=" + w-full px-3.5 py-2.5 rounded-lg border border-gray-300 bg-white + text-sm text-gray-900 placeholder-gray-400 + transition-colors duration-200 + focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 + disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed + " + /> +
+); + +/* ────────────────────────── Textarea ────────────────────────── */ + +interface FormTextareaProps { + id: string; + label: string; + value: string; + onChange: (value: string) => void; + placeholder?: string; + rows?: number; +} + +const FormTextarea: React.FC = ({ + id, + label, + value, + onChange, + placeholder, + rows = 3, +}) => ( +
+ +