LocationsView.tsx 11.6 KB
import React, { useState } from 'react';
import { 
  Search, 
  Plus, 
  Download, 
  Upload, 
  Edit, 
  MapPin, 
  Phone, 
  Mail, 
  MoreHorizontal 
} from 'lucide-react';
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../ui/table";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "../ui/dialog";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "../ui/select";
import { Label } from "../ui/label";
import { Badge } from "../ui/badge";
import { Switch } from "../ui/switch";

// --- Mock Data ---

const MOCK_LOCATIONS = [
  { 
    id: '12345', 
    name: 'Downtown Store', 
    street: '123 Main St', 
    city: 'New York', 
    state: 'NY', 
    country: 'USA', 
    zipCode: '10001',
    phone: '+1 (555) 123-4567', 
    email: 'downtown@example.com', 
    gps: '40.7128° N, 74.0060° W',
    status: 'active'
  },
  { 
    id: '12335', 
    name: 'Uptown Market', 
    street: '456 High St', 
    city: 'New York', 
    state: 'NY', 
    country: 'USA', 
    zipCode: '10002',
    phone: '+1 (555) 987-6543', 
    email: 'uptown@example.com', 
    gps: '40.7580° N, 73.9855° W',
    status: 'active'
  },
  { 
    id: '12445', 
    name: 'Airport Kiosk', 
    street: 'Terminal 4, JFK Airport', 
    city: 'Jamaica', 
    state: 'NY', 
    country: 'USA', 
    zipCode: '11430',
    phone: '+1 (555) 555-5555', 
    email: 'jfk@example.com', 
    gps: '40.6413° N, 73.7781° W',
    status: 'active'
  },
  { 
    id: '12555', 
    name: 'Suburban Outlet', 
    street: '789 Country Rd', 
    city: 'Long Island', 
    state: 'NY', 
    country: 'USA', 
    zipCode: '11901',
    phone: '+1 (555) 111-2222', 
    email: 'suburb@example.com', 
    gps: '40.8500° N, 73.2000° W',
    status: 'inactive'
  },
];

export function LocationsView() {
  const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
  const [locations, setLocations] = useState(MOCK_LOCATIONS);

  return (
    <div className="h-full flex flex-col">
      {/* Toolbar - no white background; spacing matches Labels (main p-8 only) */}
      <div className="pb-4">
        <div className="flex flex-col gap-4">
          {/* Toolbar: Search + Filters + Actions in one row, no "Search" label */}
          <div className="flex flex-nowrap items-center gap-3">
            <Input
              placeholder="Search"
              style={{ height: 40, boxSizing: 'border-box' }}
              className="border border-gray-300 rounded-md w-40 shrink-0 bg-white placeholder:text-gray-500"
            />
            <Select defaultValue="partner-a">
              <SelectTrigger className="w-[140px] h-10 rounded-md border border-gray-300 bg-white font-medium text-gray-900 shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Partner" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="partner-a">Partner A</SelectItem>
              </SelectContent>
            </Select>
            <Select defaultValue="group-b">
              <SelectTrigger className="w-[140px] h-10 rounded-md border border-gray-300 bg-white font-medium text-gray-900 shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Group" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="group-b">Group B</SelectItem>
              </SelectContent>
            </Select>
            <Select defaultValue="all">
              <SelectTrigger className="w-[140px] h-10 rounded-md border border-gray-300 bg-white font-medium text-gray-900 shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Location" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Locations</SelectItem>
                <SelectItem value="loc-1">Location 1</SelectItem>
              </SelectContent>
            </Select>
            <div className="flex-1" />
            <Button variant="outline" className="h-10 border border-gray-300 rounded-md text-gray-900 px-4 bg-white hover:bg-gray-50 shrink-0">
              Bulk Import
            </Button>
            <Button variant="outline" className="h-10 border border-gray-300 rounded-md text-gray-900 px-4 bg-white hover:bg-gray-50 shrink-0">
              Bulk Export
            </Button>
            <Button variant="outline" className="h-10 border border-gray-300 rounded-md text-gray-900 px-4 bg-white hover:bg-gray-50 shrink-0">
              Bulk Edit
            </Button>
            <Button
              className="h-10 bg-blue-600 hover:bg-blue-700 text-white rounded-md px-6 font-medium shrink-0"
              onClick={() => setIsCreateDialogOpen(true)}
            >
              New+
            </Button>
          </div>
        </div>
      </div>

      {/* Content Area - same padding as Labels (relies on main p-8) */}
      <div className="flex-1 overflow-auto pt-6">
        <div className="bg-white border border-gray-200 shadow-sm rounded-md overflow-hidden">
          <Table>
            <TableHeader>
              <TableRow className="bg-gray-100 hover:bg-gray-100">
                <TableHead className="text-gray-900 font-bold border-r">Location ID</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">Location Name</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">Street</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">City</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">State</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">Country</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">Zip Code</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">Phone</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">Email</TableHead>
                <TableHead className="text-gray-900 font-bold border-r">GPS</TableHead>
                <TableHead className="text-gray-900 font-bold text-center">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {locations.map((loc) => (
                <TableRow key={loc.id}>
                  <TableCell className="border-r font-numeric text-gray-600">{loc.id}</TableCell>
                  <TableCell className="border-r font-medium text-black">{loc.name}</TableCell>
                  <TableCell className="border-r text-gray-600 max-w-[140px] truncate">{loc.street}</TableCell>
                  <TableCell className="border-r text-gray-600">{loc.city}</TableCell>
                  <TableCell className="border-r text-gray-600">{loc.state}</TableCell>
                  <TableCell className="border-r text-gray-600">{loc.country}</TableCell>
                  <TableCell className="border-r text-gray-600 font-numeric">{loc.zipCode}</TableCell>
                  <TableCell className="border-r text-gray-600 whitespace-nowrap">{loc.phone}</TableCell>
                  <TableCell className="border-r text-gray-600 text-sm">{loc.email}</TableCell>
                  <TableCell className="border-r text-gray-500 font-numeric text-xs">{loc.gps}</TableCell>
                  <TableCell className="text-center">
                     <Button variant="ghost" size="icon" className="h-8 w-8">
                       <MoreHorizontal className="h-4 w-4 text-gray-500" />
                     </Button>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </div>
      </div>

      <CreateLocationDialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen} />
    </div>
  );
}

// --- Sub-components ---

function CreateLocationDialog({ open, onOpenChange }: { open: boolean; onOpenChange: (open: boolean) => void }) {
  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[600px]">
        <DialogHeader>
          <DialogTitle>Add New Location</DialogTitle>
          <DialogDescription>
            Enter the details for the new store location.
          </DialogDescription>
        </DialogHeader>
        
        <div className="grid gap-4 py-4">
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Partner</Label>
              <Select defaultValue="partner-a">
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="partner-a">Partner A</SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>Group</Label>
              <Select defaultValue="group-b">
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="group-b">Group B</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid grid-cols-3 gap-4">
             <div className="space-y-2 col-span-1">
              <Label>Location ID</Label>
              <Input placeholder="e.g. 12345" />
            </div>
            <div className="space-y-2 col-span-2">
              <Label>Location Name</Label>
              <Input placeholder="e.g. Downtown Store" />
            </div>
          </div>

          <div className="space-y-2">
            <Label>Street</Label>
            <Input placeholder="e.g. 123 Main St" />
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>City</Label>
              <Input placeholder="e.g. New York" />
            </div>
            <div className="space-y-2">
              <Label>State</Label>
              <Input placeholder="e.g. NY" />
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Country</Label>
              <Input placeholder="e.g. USA" />
            </div>
            <div className="space-y-2">
              <Label>Zip Code</Label>
              <Input placeholder="e.g. 10001" />
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Phone Number</Label>
              <Input placeholder="+1 (555) 000-0000" />
            </div>
            <div className="space-y-2">
              <Label>Email</Label>
              <Input placeholder="store@example.com" />
            </div>
          </div>

          <div className="space-y-2">
            <Label className="flex items-center gap-2">
              <MapPin className="w-4 h-4" /> GPS Coordinates
            </Label>
            <div className="grid grid-cols-2 gap-4">
              <Input placeholder="Latitude (e.g. 40.7128)" />
              <Input placeholder="Longitude (e.g. -74.0060)" />
            </div>
          </div>

           <div className="flex items-center gap-2 pt-2">
            <Switch id="loc-status" defaultChecked />
            <Label htmlFor="loc-status">Active Location</Label>
          </div>

        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>Cancel</Button>
          <Button onClick={() => onOpenChange(false)} className="bg-blue-600 text-white hover:bg-blue-700">Create Location</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}