refactor: adopt shared Input/Textarea components #101

Merged
chihlasm merged 9 commits from refactor/adopt-input-textarea into main 2026-03-09 20:12:22 +00:00
16 changed files with 64 additions and 0 deletions
Showing only changes of commit 337d933fe2 - Show all commits

View File

@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { Building2, Users, Mail, Crown, Loader2, AlertCircle, Check, X, Settings, FolderTree, Server, RefreshCw, MessageSquareText, UserCog, AlertTriangle, Clock } from 'lucide-react' import { Building2, Users, Mail, Crown, Loader2, AlertCircle, Check, X, Settings, FolderTree, Server, RefreshCw, MessageSquareText, UserCog, AlertTriangle, Clock } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { accountsApi } from '@/api/accounts' import { accountsApi } from '@/api/accounts'
import type { Account, AccountMember, AccountInvite } from '@/types' import type { Account, AccountMember, AccountInvite } from '@/types'
import { TransferOwnershipModal } from '@/components/account/TransferOwnershipModal' import { TransferOwnershipModal } from '@/components/account/TransferOwnershipModal'
@@ -159,6 +160,8 @@ export function AccountSettingsPage() {
const sub = subscription?.subscription const sub = subscription?.subscription
return ( return (
<>
<PageMeta title="Account Settings" />
<div> <div>
<div className="mb-8"> <div className="mb-8">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
@@ -678,6 +681,7 @@ export function AccountSettingsPage() {
<DeleteAccountModal onClose={() => setShowDeleteModal(false)} /> <DeleteAccountModal onClose={() => setShowDeleteModal(false)} />
)} )}
</div> </div>
</>
) )
} }

View File

@@ -1,5 +1,6 @@
import { useState, useEffect, useRef, useCallback } from 'react' import { useState, useEffect, useRef, useCallback } from 'react'
import { Sparkles, Send, Loader2, Flag } from 'lucide-react' import { Sparkles, Send, Loader2, Flag } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { assistantChatApi } from '@/api/assistantChat' import { assistantChatApi } from '@/api/assistantChat'
import { toast } from '@/lib/toast' import { toast } from '@/lib/toast'
import { ChatSidebar } from '@/components/assistant/ChatSidebar' import { ChatSidebar } from '@/components/assistant/ChatSidebar'
@@ -179,6 +180,8 @@ export default function AssistantChatPage() {
} }
return ( return (
<>
<PageMeta title="AI Assistant" />
<div className="flex h-[calc(100vh-3.5rem)]"> <div className="flex h-[calc(100vh-3.5rem)]">
{/* Sidebar */} {/* Sidebar */}
<ChatSidebar <ChatSidebar
@@ -303,5 +306,6 @@ export default function AssistantChatPage() {
chatTitle={chats.find(c => c.id === activeChatId)?.title ?? 'Chat'} chatTitle={chats.find(c => c.id === activeChatId)?.title ?? 'Chat'}
/> />
</div> </div>
</>
) )
} }

View File

@@ -1,5 +1,6 @@
import { useState, useRef, useEffect } from 'react' import { useState, useRef, useEffect } from 'react'
import { MessageSquareText, Send, CheckCircle2, ChevronDown } from 'lucide-react' import { MessageSquareText, Send, CheckCircle2, ChevronDown } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { useAuthStore } from '@/store/authStore' import { useAuthStore } from '@/store/authStore'
import { feedbackApi } from '@/api' import { feedbackApi } from '@/api'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
@@ -130,6 +131,8 @@ export function FeedbackPage() {
} }
return ( return (
<>
<PageMeta title="Feedback" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
{/* Page header */} {/* Page header */}
<div className="mb-8"> <div className="mb-8">
@@ -273,6 +276,7 @@ export function FeedbackPage() {
)} )}
</div> </div>
</div> </div>
</>
) )
} }

View File

@@ -2,6 +2,7 @@ import { useState } from 'react'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { authApi } from '@/api/auth' import { authApi } from '@/api/auth'
import { BrandLogo } from '@/components/common/BrandLogo' import { BrandLogo } from '@/components/common/BrandLogo'
import { PageMeta } from '@/components/common/PageMeta'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
export function ForgotPasswordPage() { export function ForgotPasswordPage() {
@@ -25,6 +26,8 @@ export function ForgotPasswordPage() {
} }
return ( return (
<>
<PageMeta title="Forgot Password" description="Reset your ResolutionFlow password" />
<div className="flex min-h-screen items-center justify-center bg-card px-4"> <div className="flex min-h-screen items-center justify-center bg-card px-4">
<div className="pointer-events-none fixed inset-0 bg-[radial-gradient(circle_at_50%_0%,rgba(100,100,120,0.03),transparent_50%)]" /> <div className="pointer-events-none fixed inset-0 bg-[radial-gradient(circle_at_50%_0%,rgba(100,100,120,0.03),transparent_50%)]" />
@@ -109,6 +112,7 @@ export function ForgotPasswordPage() {
)} )}
</div> </div>
</div> </div>
</>
) )
} }

View File

@@ -1,9 +1,12 @@
import { BookOpen } from 'lucide-react' import { BookOpen } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { guides } from '@/data/guides' import { guides } from '@/data/guides'
import { GuideCard } from '@/components/guides/GuideCard' import { GuideCard } from '@/components/guides/GuideCard'
export default function GuidesHubPage() { export default function GuidesHubPage() {
return ( return (
<>
<PageMeta title="Guides" />
<div className="p-6 max-w-5xl mx-auto"> <div className="p-6 max-w-5xl mx-auto">
{/* Header */} {/* Header */}
<div className="mb-8"> <div className="mb-8">
@@ -25,5 +28,6 @@ export default function GuidesHubPage() {
))} ))}
</div> </div>
</div> </div>
</>
) )
} }

View File

@@ -3,6 +3,7 @@ import { Link, useNavigate, useLocation } from 'react-router-dom'
import { useAuthStore } from '@/store/authStore' import { useAuthStore } from '@/store/authStore'
import { BrandLogo } from '@/components/common/BrandLogo' import { BrandLogo } from '@/components/common/BrandLogo'
import { PasswordInput } from '@/components/common/PasswordInput' import { PasswordInput } from '@/components/common/PasswordInput'
import { PageMeta } from '@/components/common/PageMeta'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
export function LoginPage() { export function LoginPage() {
@@ -40,6 +41,8 @@ export function LoginPage() {
} }
return ( return (
<>
<PageMeta title="Sign In" description="Sign in to your ResolutionFlow account" />
<div className="flex min-h-screen items-center justify-center bg-background px-4"> <div className="flex min-h-screen items-center justify-center bg-background px-4">
{/* Atmosphere orbs */} {/* Atmosphere orbs */}
<div <div
@@ -164,6 +167,7 @@ export function LoginPage() {
</form> </form>
</div> </div>
</div> </div>
</>
) )
} }

View File

@@ -1,6 +1,7 @@
import { useState, useEffect, useCallback } from 'react' import { useState, useEffect, useCallback } from 'react'
import { Link, useNavigate } from 'react-router-dom' import { Link, useNavigate } from 'react-router-dom'
import { Globe, Users, Copy, Check, Link2, ExternalLink, Trash2, ArrowLeft } from 'lucide-react' import { Globe, Users, Copy, Check, Link2, ExternalLink, Trash2, ArrowLeft } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { Button } from '@/components/ui/Button' import { Button } from '@/components/ui/Button'
import { Spinner } from '@/components/common/Spinner' import { Spinner } from '@/components/common/Spinner'
import { EmptyState } from '@/components/common/EmptyState' import { EmptyState } from '@/components/common/EmptyState'
@@ -121,6 +122,8 @@ export default function MySharesPage() {
} }
return ( return (
<>
<PageMeta title="My Shares" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
{/* Back link */} {/* Back link */}
<Link <Link
@@ -241,5 +244,6 @@ export default function MySharesPage() {
confirmLabel="Revoke" confirmLabel="Revoke"
/> />
</div> </div>
</>
) )
} }

View File

@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useNavigate, Link } from 'react-router-dom' import { useNavigate, Link } from 'react-router-dom'
import { Play, Pencil, Share2, Trash2, GitBranch, Clock, TrendingUp, FolderTree, Plus, ListOrdered, ChevronDown, Wrench } from 'lucide-react' import { Play, Pencil, Share2, Trash2, GitBranch, Clock, TrendingUp, FolderTree, Plus, ListOrdered, ChevronDown, Wrench } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { Button } from '@/components/ui/Button' import { Button } from '@/components/ui/Button'
import { treesApi } from '@/api/trees' import { treesApi } from '@/api/trees'
import { sessionsApi } from '@/api/sessions' import { sessionsApi } from '@/api/sessions'
@@ -116,6 +117,8 @@ export function MyTreesPage() {
} }
return ( return (
<>
<PageMeta title="My Flows" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
<div className="mb-6 flex items-center justify-between sm:mb-8"> <div className="mb-6 flex items-center justify-between sm:mb-8">
<div> <div>
@@ -389,6 +392,7 @@ export function MyTreesPage() {
)} )}
</div> </div>
</>
) )
} }

View File

@@ -1,6 +1,7 @@
import { useState, useEffect, useRef, useMemo, useCallback } from 'react' import { useState, useEffect, useRef, useMemo, useCallback } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { Search, Loader2, Star, ChevronLeft, ChevronRight, GitBranch } from 'lucide-react' import { Search, Loader2, Star, ChevronLeft, ChevronRight, GitBranch } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { treesApi } from '@/api/trees' import { treesApi } from '@/api/trees'
import { sessionsApi } from '@/api/sessions' import { sessionsApi } from '@/api/sessions'
import type { TreeListItem, TreeFilters } from '@/types' import type { TreeListItem, TreeFilters } from '@/types'
@@ -277,6 +278,8 @@ export function QuickStartPage() {
] ]
return ( return (
<>
<PageMeta title="Dashboard" />
<div className="p-6 space-y-6"> <div className="p-6 space-y-6">
{/* Greeting */} {/* Greeting */}
<div className="fade-in" style={{ animationDelay: '100ms' }}> <div className="fade-in" style={{ animationDelay: '100ms' }}>
@@ -646,6 +649,7 @@ export function QuickStartPage() {
)} )}
</div> </div>
</>
) )
} }

View File

@@ -4,6 +4,7 @@ import { useAuthStore } from '@/store/authStore'
import { inviteApi } from '@/api/invite' import { inviteApi } from '@/api/invite'
import { BrandLogo } from '@/components/common/BrandLogo' import { BrandLogo } from '@/components/common/BrandLogo'
import { PasswordInput } from '@/components/common/PasswordInput' import { PasswordInput } from '@/components/common/PasswordInput'
import { PageMeta } from '@/components/common/PageMeta'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
export function RegisterPage() { export function RegisterPage() {
@@ -76,6 +77,8 @@ export function RegisterPage() {
} }
return ( return (
<>
<PageMeta title="Create Account" description="Create your ResolutionFlow account to start building guided troubleshooting flows" />
<div className="flex min-h-screen items-center justify-center bg-black px-4"> <div className="flex min-h-screen items-center justify-center bg-black px-4">
{/* Subtle radial overlay */} {/* Subtle radial overlay */}
<div className="pointer-events-none fixed inset-0 bg-[radial-gradient(circle_at_50%_0%,rgba(100,100,120,0.03),transparent_50%)]" /> <div className="pointer-events-none fixed inset-0 bg-[radial-gradient(circle_at_50%_0%,rgba(100,100,120,0.03),transparent_50%)]" />
@@ -251,6 +254,7 @@ export function RegisterPage() {
</form> </form>
</div> </div>
</div> </div>
</>
) )
} }

View File

@@ -4,6 +4,7 @@ import { authApi } from '@/api/auth'
import { toast } from '@/lib/toast' import { toast } from '@/lib/toast'
import { BrandLogo } from '@/components/common/BrandLogo' import { BrandLogo } from '@/components/common/BrandLogo'
import { PasswordInput } from '@/components/common/PasswordInput' import { PasswordInput } from '@/components/common/PasswordInput'
import { PageMeta } from '@/components/common/PageMeta'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
export function ResetPasswordPage() { export function ResetPasswordPage() {
@@ -72,6 +73,8 @@ export function ResetPasswordPage() {
} }
return ( return (
<>
<PageMeta title="Reset Password" description="Set a new password for your ResolutionFlow account" />
<div className="flex min-h-screen items-center justify-center bg-black px-4"> <div className="flex min-h-screen items-center justify-center bg-black px-4">
<div className="pointer-events-none fixed inset-0 bg-[radial-gradient(circle_at_50%_0%,rgba(100,100,120,0.03),transparent_50%)]" /> <div className="pointer-events-none fixed inset-0 bg-[radial-gradient(circle_at_50%_0%,rgba(100,100,120,0.03),transparent_50%)]" />
@@ -180,6 +183,7 @@ export function ResetPasswordPage() {
)} )}
</div> </div>
</div> </div>
</>
) )
} }

View File

@@ -1,5 +1,6 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom' import { useNavigate, useSearchParams } from 'react-router-dom'
import { PageMeta } from '@/components/common/PageMeta'
import { sessionsApi } from '@/api/sessions' import { sessionsApi } from '@/api/sessions'
import { treesApi } from '@/api/trees' import { treesApi } from '@/api/trees'
import type { Session, TreeListItem } from '@/types' import type { Session, TreeListItem } from '@/types'
@@ -154,6 +155,8 @@ export function SessionHistoryPage() {
} }
return ( return (
<>
<PageMeta title="Session History" />
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
<div className="mb-8"> <div className="mb-8">
<h1 className="text-2xl font-heading font-bold text-foreground sm:text-3xl">Session History</h1> <h1 className="text-2xl font-heading font-bold text-foreground sm:text-3xl">Session History</h1>
@@ -310,6 +313,7 @@ export function SessionHistoryPage() {
</div> </div>
)} )}
</div> </div>
</>
) )
} }

View File

@@ -1,5 +1,6 @@
import { useState } from 'react' import { useState } from 'react'
import { Bookmark, Trash2 } from 'lucide-react' import { Bookmark, Trash2 } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { Button } from '@/components/ui/Button' import { Button } from '@/components/ui/Button'
import { useAuthStore } from '@/store/authStore' import { useAuthStore } from '@/store/authStore'
import { usePermissions } from '@/hooks/usePermissions' import { usePermissions } from '@/hooks/usePermissions'
@@ -87,6 +88,8 @@ export default function StepLibraryPage() {
} }
return ( return (
<>
<PageMeta title="Step Library" />
<div className="flex h-full flex-col"> <div className="flex h-full flex-col">
{/* Page Header */} {/* Page Header */}
<div className="flex items-center justify-between border-b border-border px-6 py-4"> <div className="flex items-center justify-between border-b border-border px-6 py-4">
@@ -167,5 +170,6 @@ export default function StepLibraryPage() {
)} )}
</div> </div>
</>
) )
} }

View File

@@ -1,7 +1,10 @@
import { BrandLogo } from '@/components/common/BrandLogo' import { BrandLogo } from '@/components/common/BrandLogo'
import { PageMeta } from '@/components/common/PageMeta'
export default function SurveyThankYouPage() { export default function SurveyThankYouPage() {
return ( return (
<>
<PageMeta title="Thank You" description="Thank you for your feedback on ResolutionFlow" />
<div className="min-h-screen bg-background text-foreground"> <div className="min-h-screen bg-background text-foreground">
{/* Atmosphere orbs */} {/* Atmosphere orbs */}
<div className="pointer-events-none fixed inset-0 z-0 overflow-hidden" aria-hidden="true"> <div className="pointer-events-none fixed inset-0 z-0 overflow-hidden" aria-hidden="true">
@@ -72,5 +75,6 @@ export default function SurveyThankYouPage() {
</div> </div>
</div> </div>
</div> </div>
</>
) )
} }

View File

@@ -1,6 +1,7 @@
import { useEffect, useState, useCallback, useMemo } from 'react' import { useEffect, useState, useCallback, useMemo } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom' import { useNavigate, useSearchParams } from 'react-router-dom'
import { X, RotateCcw, Play, FileUp } from 'lucide-react' import { X, RotateCcw, Play, FileUp } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { Button } from '@/components/ui/Button' import { Button } from '@/components/ui/Button'
import { treesApi } from '@/api/trees' import { treesApi } from '@/api/trees'
import { categoriesApi } from '@/api/categories' import { categoriesApi } from '@/api/categories'
@@ -265,6 +266,8 @@ export function TreeLibraryPage() {
selectedCategoryId || selectedTags.length > 0 || searchQuery || selectedFolderId selectedCategoryId || selectedTags.length > 0 || searchQuery || selectedFolderId
return ( return (
<>
<PageMeta title="Flow Library" />
<div className="min-h-full"> <div className="min-h-full">
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8"> <div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
<div className="mb-6 flex flex-col gap-4 sm:mb-8 sm:flex-row sm:items-start sm:justify-between"> <div className="mb-6 flex flex-col gap-4 sm:mb-8 sm:flex-row sm:items-start sm:justify-between">
@@ -596,6 +599,7 @@ export function TreeLibraryPage() {
/> />
)} )}
</div> </div>
</>
) )
} }

View File

@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
import { useSearchParams, Link } from 'react-router-dom' import { useSearchParams, Link } from 'react-router-dom'
import { CheckCircle2, XCircle, Loader2 } from 'lucide-react' import { CheckCircle2, XCircle, Loader2 } from 'lucide-react'
import { authApi } from '@/api/auth' import { authApi } from '@/api/auth'
import { PageMeta } from '@/components/common/PageMeta'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
export function VerifyEmailPage() { export function VerifyEmailPage() {
@@ -23,6 +24,8 @@ export function VerifyEmailPage() {
}, [token]) }, [token])
return ( return (
<>
<PageMeta title="Verify Email" description="Verify your ResolutionFlow email address" />
<div className="flex min-h-screen items-center justify-center bg-background p-4"> <div className="flex min-h-screen items-center justify-center bg-background p-4">
<div className="glass-card-static w-full max-w-md p-8 text-center"> <div className="glass-card-static w-full max-w-md p-8 text-center">
{status === 'loading' && ( {status === 'loading' && (
@@ -65,6 +68,7 @@ export function VerifyEmailPage() {
)} )}
</div> </div>
</div> </div>
</>
) )
} }