Replace native selects with shadcn Select across all pages
Build & Auto-Repair / build (push) Has been cancelled
Build & Auto-Repair / build (push) Has been cancelled
- lead-scoring-settings.tsx: Feature type dropdown - bug-report-modal.tsx: Severity dropdown - client-portal/support/page.tsx: Severity dropdown - time-tracking/page.tsx: Timer project + manual entry project dropdowns - proposals/new/page.tsx: Lead + customer dropdowns
This commit is contained in:
@@ -137,21 +137,29 @@ export default function NewProposalPage() {
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium">Lead (optional)</label>
|
||||
<select value={leadId} onChange={(e) => setLeadId(e.target.value)} className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm">
|
||||
<option value="">Select lead...</option>
|
||||
<Select value={leadId} onValueChange={setLeadId}>
|
||||
<SelectTrigger className="h-9 w-full">
|
||||
<SelectValue placeholder="Select lead..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{leads.map((l: any) => (
|
||||
<option key={l.id} value={l.id}>{l.contact_name || l.company_name}</option>
|
||||
<SelectItem key={l.id} value={l.id}>{l.contact_name || l.company_name}</SelectItem>
|
||||
))}
|
||||
</select>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium">Customer (optional)</label>
|
||||
<select value={customerId} onChange={(e) => setCustomerId(e.target.value)} className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm">
|
||||
<option value="">Select customer...</option>
|
||||
<Select value={customerId} onValueChange={setCustomerId}>
|
||||
<SelectTrigger className="h-9 w-full">
|
||||
<SelectValue placeholder="Select customer..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{customers.map((c: any) => (
|
||||
<option key={c.id} value={c.id}>{c.company_name || `${c.first_name} ${c.last_name}`}</option>
|
||||
<SelectItem key={c.id} value={c.id}>{c.company_name || `${c.first_name} ${c.last_name}`}</SelectItem>
|
||||
))}
|
||||
</select>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium">VAT %</label>
|
||||
|
||||
@@ -6,6 +6,13 @@ import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Card } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
import { Play, Square, Plus, Trash2, Clock, Briefcase, User, TrendingUp, DollarSign } from "lucide-react"
|
||||
import { toast } from "sonner"
|
||||
|
||||
@@ -29,7 +36,7 @@ export default function TimeTrackingPage() {
|
||||
const [showManual, setShowManual] = useState(false)
|
||||
|
||||
// Manual entry form
|
||||
const [manualProject, setManualProject] = useState("")
|
||||
const [manualProject, setManualProject] = useState("none")
|
||||
const [manualDesc, setManualDesc] = useState("")
|
||||
const [manualDate, setManualDate] = useState(new Date().toISOString().split("T")[0])
|
||||
const [manualHours, setManualHours] = useState("")
|
||||
@@ -41,7 +48,7 @@ export default function TimeTrackingPage() {
|
||||
// Timer
|
||||
const [timerRunning, setTimerRunning] = useState(false)
|
||||
const [timerSeconds, setTimerSeconds] = useState(0)
|
||||
const [timerProject, setTimerProject] = useState("")
|
||||
const [timerProject, setTimerProject] = useState("none")
|
||||
const [timerDesc, setTimerDesc] = useState("")
|
||||
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null)
|
||||
const startTimeRef = useRef<Date | null>(null)
|
||||
@@ -92,7 +99,7 @@ export default function TimeTrackingPage() {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
projectId: timerProject || null,
|
||||
projectId: timerProject === "none" ? null : timerProject,
|
||||
description: timerDesc,
|
||||
date: new Date().toISOString().split("T")[0],
|
||||
startTime: startTimeRef.current?.toISOString(),
|
||||
@@ -103,7 +110,7 @@ export default function TimeTrackingPage() {
|
||||
}),
|
||||
})
|
||||
setTimerDesc("")
|
||||
setTimerProject("")
|
||||
setTimerProject("none")
|
||||
setTimerSeconds(0)
|
||||
fetchData()
|
||||
} catch (e) {
|
||||
@@ -124,7 +131,7 @@ export default function TimeTrackingPage() {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
projectId: manualProject || null,
|
||||
projectId: manualProject === "none" ? null : manualProject,
|
||||
description: manualDesc,
|
||||
date: manualDate,
|
||||
durationMinutes: totalMins,
|
||||
@@ -212,10 +219,15 @@ export default function TimeTrackingPage() {
|
||||
<div className="flex items-end gap-3">
|
||||
<div className="flex-1 space-y-2">
|
||||
<Input placeholder="What are you working on?" value={timerDesc} onChange={(e) => setTimerDesc(e.target.value)} className="h-9" disabled={timerRunning} />
|
||||
<select value={timerProject} onChange={(e) => setTimerProject(e.target.value)} className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm" disabled={timerRunning}>
|
||||
<option value="">No project</option>
|
||||
{projects.map((p: any) => <option key={p.id} value={p.id}>{p.name}</option>)}
|
||||
</select>
|
||||
<Select value={timerProject} onValueChange={setTimerProject} disabled={timerRunning}>
|
||||
<SelectTrigger className="h-9 w-full">
|
||||
<SelectValue placeholder="No project" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">No project</SelectItem>
|
||||
{projects.map((p: any) => <SelectItem key={p.id} value={p.id}>{p.name}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="text-3xl font-mono font-bold tabular-nums px-4 py-1">{formatTimer(timerSeconds)}</div>
|
||||
{!timerRunning ? (
|
||||
@@ -238,10 +250,15 @@ export default function TimeTrackingPage() {
|
||||
<div className="space-y-3 p-3 rounded-lg border bg-muted/20">
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
<Input placeholder="Description *" value={manualDesc} onChange={(e) => setManualDesc(e.target.value)} className="h-8 text-sm" />
|
||||
<select value={manualProject} onChange={(e) => setManualProject(e.target.value)} className="flex h-8 w-full rounded-md border border-input bg-transparent px-3 text-sm shadow-sm">
|
||||
<option value="">No project</option>
|
||||
{projects.map((p: any) => <option key={p.id} value={p.id}>{p.name}</option>)}
|
||||
</select>
|
||||
<Select value={manualProject} onValueChange={setManualProject}>
|
||||
<SelectTrigger className="h-8 w-full">
|
||||
<SelectValue placeholder="No project" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">No project</SelectItem>
|
||||
{projects.map((p: any) => <SelectItem key={p.id} value={p.id}>{p.name}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
<Input type="date" value={manualDate} onChange={(e) => setManualDate(e.target.value)} className="h-8 w-40 text-sm" />
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
import { LifeBuoy, Send } from "lucide-react"
|
||||
|
||||
interface Ticket {
|
||||
@@ -107,16 +114,17 @@ export default function ClientSupport() {
|
||||
|
||||
<div>
|
||||
<label className="block text-sm text-[#8a8a95] mb-1">Severity</label>
|
||||
<select
|
||||
value={severity}
|
||||
onChange={(e) => setSeverity(e.target.value)}
|
||||
className="w-full bg-[#1a1a24] border border-[#2a2a35] rounded-lg px-3 py-2 text-sm text-white outline-none focus:border-[#1BB0CE]/50"
|
||||
>
|
||||
<option value="low">Low</option>
|
||||
<option value="medium">Medium</option>
|
||||
<option value="high">High</option>
|
||||
<option value="critical">Critical</option>
|
||||
</select>
|
||||
<Select value={severity} onValueChange={setSeverity}>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="low">Low</SelectItem>
|
||||
<SelectItem value="medium">Medium</SelectItem>
|
||||
<SelectItem value="high">High</SelectItem>
|
||||
<SelectItem value="critical">Critical</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{submitError && (
|
||||
|
||||
@@ -5,6 +5,13 @@ import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
import { Plus, Trash2, RefreshCw, Gauge } from "lucide-react"
|
||||
import { toast } from "sonner"
|
||||
|
||||
@@ -142,11 +149,16 @@ export function LeadScoringSettings() {
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-medium">Type</label>
|
||||
<select value={newFeature.featureType} onChange={e => setNewFeature(p => ({ ...p, featureType: e.target.value }))} className="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm">
|
||||
<option value="keyword">Keyword Match</option>
|
||||
<option value="boolean">Boolean (has value)</option>
|
||||
<option value="range">Range</option>
|
||||
</select>
|
||||
<Select value={newFeature.featureType} onValueChange={v => setNewFeature(p => ({ ...p, featureType: v }))}>
|
||||
<SelectTrigger className="h-9 w-full">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="keyword">Keyword Match</SelectItem>
|
||||
<SelectItem value="boolean">Boolean (has value)</SelectItem>
|
||||
<SelectItem value="range">Range</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-medium">Weight</label>
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
import { useState } from "react"
|
||||
import { motion, AnimatePresence } from "framer-motion"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
import { X, Bug, Loader2, CheckCircle } from "lucide-react"
|
||||
|
||||
interface BugReportModalProps {
|
||||
@@ -151,16 +158,17 @@ export function BugReportModal({ open, onClose }: BugReportModalProps) {
|
||||
<label className="mb-1.5 block text-sm font-medium text-[#8A9078] dark:text-[#CCCCCC]">
|
||||
Severity
|
||||
</label>
|
||||
<select
|
||||
value={severity}
|
||||
onChange={(e) => setSeverity(e.target.value)}
|
||||
className="w-full rounded-lg border border-[#D4D8CC] dark:border-[#333333] bg-white dark:bg-[#1E1E1E] px-3 py-2 text-sm text-[#2D3020] dark:text-white focus:border-[#C84B4B] focus:outline-none focus:ring-1 focus:ring-[#C84B4B]"
|
||||
>
|
||||
<option value="low">Low — Minor cosmetic issue</option>
|
||||
<option value="medium">Medium — Affects functionality</option>
|
||||
<option value="high">High — Major feature broken</option>
|
||||
<option value="critical">Critical — System is blocked</option>
|
||||
</select>
|
||||
<Select value={severity} onValueChange={setSeverity}>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="low">Low — Minor cosmetic issue</SelectItem>
|
||||
<SelectItem value="medium">Medium — Affects functionality</SelectItem>
|
||||
<SelectItem value="high">High — Major feature broken</SelectItem>
|
||||
<SelectItem value="critical">Critical — System is blocked</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg bg-[#FAFAF6] dark:bg-[#1A1A1A] px-3 py-2">
|
||||
|
||||
Reference in New Issue
Block a user