{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "property-filters",
  "type": "registry:component",
  "title": "Property Filters",
  "author": "Toby Belhome",
  "description": "Enable users to quickly find properties with Tailwind CSS property filter sections. These layouts offer checkboxes, dropdowns, and tags to refine searches, improving usability and property discovery. Perfect for real estate websites and marketplaces seeking modern, efficient, and user-friendly browsing experiences.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "button",
    "card",
    "checkbox",
    "label",
    "slider",
    "badge",
    "avatar",
    "switch"
  ],
  "files": [
    {
      "path": "examples/blocks/real-estate/property-filters/01/page.tsx",
      "content": "\"use client\";\n\nimport { useState, useMemo } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card, CardAction, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { Label } from \"@/components/ui/label\";\nimport { Slider } from \"@/components/ui/slider\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue\n} from \"@/components/ui/select\";\nimport { Switch } from \"@/components/ui/switch\";\nimport { Check, Info } from \"lucide-react\";\n\nconst properties = [\n  {\n    id: 1,\n    title: \"3 BHK Residential Apartment in Ayyapakkam\",\n    location: \"BBCL Ayyapakkam\",\n    price: 95000,\n    pricePerSqFt: 73,\n    area: 1305,\n    areaDetails: \"(121 sq.m.) Super built-up Area\",\n    bhk: 3,\n    baths: 2,\n    description:\n      \"Residential apartment for sale in BBCL Ayyapakkam, Chennai. This property promises a contented and comfortable lifestyle with modern amenities and excellent connectivity.\",\n    verified: true,\n    postedDate: \"April 22, 2020\",\n    owner: \"Inez Freeman\",\n    image:\n      \"https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    society: \"vijay\",\n    furnishing: \"furnished\",\n    underConstruction: false,\n    readyToMove: true,\n    hasPhotos: true\n  },\n  {\n    id: 2,\n    title: \"3 BHK Residential Apartment in K.K. Nagar\",\n    location: \"NML K.K. Nagar\",\n    price: 98000,\n    pricePerSqFt: 75,\n    area: 1305,\n    areaDetails: \"(121 sq.m.) Super built-up Area\",\n    bhk: 3,\n    baths: 2,\n    description:\n      \"This beautiful east facing, Vastu compliant unit is situated on ground of 2 floors, in a builder floor building with premium finishes and great natural light.\",\n    verified: false,\n    postedDate: \"May 13, 2020\",\n    owner: \"Carrie Reyes\",\n    image:\n      \"https://images.unsplash.com/photo-1580587771525-78b9dba3b914?q=80&w=2574&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    society: \"olympia\",\n    furnishing: \"Semi furnished\",\n    underConstruction: true,\n    readyToMove: false,\n    hasPhotos: true\n  },\n  {\n    id: 3,\n    title: \"3 BHK Residential Apartment in Lancor Abode Valley\",\n    location: \"Lancor Abode Valley, Potheri\",\n    price: 92000,\n    pricePerSqFt: 70,\n    area: 1305,\n    areaDetails: \"(121 sq.m.) Super built-up Area\",\n    bhk: 3,\n    baths: 2,\n    description:\n      \"This builder floor is a semi-furnished unit and consists of one wardrobe, AC, fans, lights and modular kitchen with excellent amenities in a gated community.\",\n    verified: true,\n    postedDate: \"June 13, 2020\",\n    owner: \"Mitchell Spencer\",\n    image:\n      \"https://plus.unsplash.com/premium_photo-1689609950112-d66095626efb?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    society: \"alliance\",\n    furnishing: \"Semi furnished\",\n    underConstruction: false,\n    readyToMove: true,\n    hasPhotos: true\n  },\n  {\n    id: 4,\n    title: \"2 BHK Apartment in Provident Cosmo City\",\n    location: \"Provident Cosmo City\",\n    price: 65000,\n    pricePerSqFt: 68,\n    area: 950,\n    areaDetails: \"(88 sq.m.) Super built-up Area\",\n    bhk: 2,\n    baths: 2,\n    description:\n      \"Spacious 2 bedroom apartment with modern amenities, gym, swimming pool and children's play area. Perfect for small families looking for quality living.\",\n    verified: true,\n    postedDate: \"March 15, 2020\",\n    owner: \"Sarah Johnson\",\n    image:\n      \"https://plus.unsplash.com/premium_photo-1689609950069-2961f80b1e70?q=80&w=1287&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    society: \"provident\",\n    furnishing: \"Fully furnished\",\n    underConstruction: false,\n    readyToMove: true,\n    hasPhotos: true\n  },\n  {\n    id: 5,\n    title: \"4 BHK Luxury Villa in KG Signature City\",\n    location: \"KG Signature City\",\n    price: 185000,\n    pricePerSqFt: 92,\n    area: 2010,\n    areaDetails: \"(187 sq.m.) Super built-up Area\",\n    bhk: 4,\n    baths: 3,\n    description:\n      \"Luxurious 4 bedroom villa with premium specifications, private garden, and exclusive clubhouse facilities. Experience elevated living in a prime location.\",\n    verified: true,\n    postedDate: \"July 8, 2020\",\n    owner: \"David Williams\",\n    image:\n      \"https://images.unsplash.com/photo-1605146769289-440113cc3d00?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    society: \"kg\",\n    furnishing: \"Unfurnished\",\n    underConstruction: false,\n    readyToMove: false,\n    hasPhotos: true\n  }\n];\n\nconst societies = [\n  { id: \"provident\", name: \"Provident Cosmo City\" },\n  { id: \"olympia\", name: \"Olympia Opaline\" },\n  { id: \"vijay\", name: \"Vijay Shanthi Lotus Pond\", checked: true },\n  { id: \"kg\", name: \"KG Signature City\" },\n  { id: \"alliance\", name: \"Alliance Orchid Springs\" }\n];\n\nexport default function RealEstateFilterPage() {\n  const [budget, setBudget] = useState([20, 200]);\n  const [selectedBedrooms, setSelectedBedrooms] = useState<number[]>([]);\n  const [selectedFurnishing, setSelectedFurnishing] = useState<string[]>([]);\n  const [selectedSocieties, setSelectedSocieties] = useState<string[]>([]);\n  const [ownerVerified, setOwnerVerified] = useState(false);\n  const [underConstruction, setUnderConstruction] = useState(false);\n  const [readyToMove, setReadyToMove] = useState(false);\n  const [withPhotos, setWithPhotos] = useState(false);\n  const [familyMode, setFamilyMode] = useState(false);\n  const [sortBy, setSortBy] = useState(\"price\");\n\n  const filteredAndSortedProperties = useMemo(() => {\n    const filtered = properties.filter((property) => {\n      // Budget filter (price in thousands)\n      if (property.price < budget[0] * 1000 || property.price > budget[1] * 1000) return false;\n\n      // Bedroom filter\n      if (selectedBedrooms.length > 0 && !selectedBedrooms.includes(property.bhk)) return false;\n\n      // Society filter\n      if (selectedSocieties.length > 0 && !selectedSocieties.includes(property.society))\n        return false;\n\n      // Furnishing filter\n      if (selectedFurnishing.length > 0 && !selectedFurnishing.includes(property.furnishing))\n        return false;\n\n      // Top filter badges\n      if (ownerVerified && !property.verified) return false;\n      if (underConstruction && !property.underConstruction) return false;\n      if (readyToMove && !property.readyToMove) return false;\n      if (withPhotos && !property.hasPhotos) return false;\n\n      return true;\n    });\n\n    // Sort filtered results\n    filtered.sort((a, b) => {\n      if (sortBy === \"price\") return a.price - b.price;\n      if (sortBy === \"area\") return b.area - a.area;\n      if (sortBy === \"date\")\n        return new Date(b.postedDate).getTime() - new Date(a.postedDate).getTime();\n      return 0;\n    });\n\n    return filtered;\n  }, [\n    budget,\n    selectedBedrooms,\n    selectedSocieties,\n    selectedFurnishing,\n    ownerVerified,\n    underConstruction,\n    readyToMove,\n    withPhotos,\n    sortBy\n  ]);\n\n  const toggleBedroom = (bedroom: number) => {\n    setSelectedBedrooms((prev) =>\n      prev.includes(bedroom) ? prev.filter((b) => b !== bedroom) : [...prev, bedroom]\n    );\n  };\n\n  const toggleFurnishing = (furnishing: string) => {\n    setSelectedFurnishing((prev) =>\n      prev.includes(furnishing) ? prev.filter((f) => f !== furnishing) : [...prev, furnishing]\n    );\n  };\n\n  const toggleSociety = (society: string) => {\n    setSelectedSocieties((prev) =>\n      prev.includes(society) ? prev.filter((s) => s !== society) : [...prev, society]\n    );\n  };\n\n  const clearAllFilters = () => {\n    setBudget([20, 200]);\n    setSelectedBedrooms([]);\n    setSelectedFurnishing([]);\n    setSelectedSocieties([]);\n    setOwnerVerified(false);\n    setUnderConstruction(false);\n    setReadyToMove(false);\n    setWithPhotos(false);\n  };\n\n  const formatPrice = (price: number) => {\n    return new Intl.NumberFormat(\"en-US\", {\n      style: \"currency\",\n      currency: \"USD\",\n      maximumFractionDigits: 0\n    }).format(price);\n  };\n\n  return (\n    <>\n      {/* Header */}\n      <header className=\"border-b\">\n        <div className=\"mx-auto max-w-7xl px-4 py-4\">\n          <div className=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n            <div className=\"flex items-center justify-between\">\n              <div>\n                <h1 className=\"text-xl font-semibold\">\n                  {filteredAndSortedProperties.length} search results\n                </h1>\n              </div>\n            </div>\n          </div>\n        </div>\n      </header>\n\n      {/* Filters Bar */}\n      <div className=\"border-b\">\n        <div className=\"mx-auto max-w-7xl px-4 py-4\">\n          <div className=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n            <div className=\"flex flex-wrap gap-2\">\n              <Badge\n                variant={ownerVerified ? \"default\" : \"secondary\"}\n                className=\"cursor-pointer px-3 py-1\"\n                onClick={() => setOwnerVerified(!ownerVerified)}>\n                Owner Verified\n              </Badge>\n              <Badge\n                variant={underConstruction ? \"default\" : \"secondary\"}\n                className=\"cursor-pointer px-3 py-1\"\n                onClick={() => setUnderConstruction(!underConstruction)}>\n                Under Construction\n              </Badge>\n              <Badge\n                variant={readyToMove ? \"default\" : \"secondary\"}\n                className=\"cursor-pointer px-3 py-1\"\n                onClick={() => setReadyToMove(!readyToMove)}>\n                Ready To Move\n              </Badge>\n              <Badge\n                variant={withPhotos ? \"default\" : \"secondary\"}\n                className=\"cursor-pointer px-3 py-1\"\n                onClick={() => setWithPhotos(!withPhotos)}>\n                With Photos\n              </Badge>\n            </div>\n            <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center\">\n              <div className=\"flex items-center gap-2\">\n                <Switch id=\"family-mode\" checked={familyMode} onCheckedChange={setFamilyMode} />\n                <Label htmlFor=\"family-mode\" className=\"flex items-center gap-1 text-sm\">\n                  Family mode <Info className=\"text-muted-foreground size-4\" />\n                </Label>\n              </div>\n              <div className=\"flex items-center gap-2\">\n                <Select value={sortBy} onValueChange={setSortBy}>\n                  <SelectTrigger id=\"sort\" className=\"\">\n                    Sort by: <SelectValue />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"price\">Price</SelectItem>\n                    <SelectItem value=\"date\">Date</SelectItem>\n                    <SelectItem value=\"area\">Area</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      {/* Main Content */}\n      <div className=\"mx-auto max-w-7xl px-4 py-6\">\n        <div className=\"grid gap-6 lg:grid-cols-[300px_1fr]\">\n          {/* Sidebar Filters */}\n          <aside className=\"space-y-4\">\n            <Card className=\"shadow-none\">\n              <CardHeader className=\"flex items-center justify-between\">\n                <CardTitle>Applied Filters</CardTitle>\n                <CardAction>\n                  <Button\n                    variant=\"ghost\"\n                    size=\"sm\"\n                    className=\"text-primary\"\n                    onClick={clearAllFilters}>\n                    Clear All\n                  </Button>\n                </CardAction>\n              </CardHeader>\n              <CardContent className=\"space-y-6\">\n                {/* Budget Filter */}\n                <div className=\"space-y-3\">\n                  <Label className=\"font-semibold\">Budget</Label>\n                  <div className=\"px-2 pt-2\">\n                    <Slider\n                      value={budget}\n                      onValueChange={setBudget}\n                      min={20}\n                      max={200}\n                      step={5}\n                      className=\"mb-4\"\n                    />\n                    <div className=\"text-muted-foreground flex justify-between text-sm\">\n                      <span>${budget[0]}k</span>\n                      <span>${budget[1]}k</span>\n                    </div>\n                  </div>\n                </div>\n\n                {/* Bedrooms Filter */}\n                <div className=\"space-y-3\">\n                  <Label className=\"font-semibold\">No. of Bedrooms</Label>\n                  <div className=\"grid grid-cols-3 gap-2\">\n                    {[1, 2, 3, 4, 6, 7, 8].map((bedroom) => (\n                      <Button\n                        key={bedroom}\n                        variant={selectedBedrooms.includes(bedroom) ? \"default\" : \"outline\"}\n                        size=\"sm\"\n                        onClick={() => toggleBedroom(bedroom)}>\n                        {bedroom}BHK\n                      </Button>\n                    ))}\n                  </div>\n                </div>\n\n                {/* Societies Filter */}\n                <div className=\"space-y-3\">\n                  <Label className=\"font-semibold\">New Projects / Societies</Label>\n                  <div className=\"space-y-2\">\n                    {societies.map((society) => (\n                      <div key={society.id} className=\"flex items-center space-x-2\">\n                        <Checkbox\n                          id={society.id}\n                          checked={selectedSocieties.includes(society.id)}\n                          onCheckedChange={() => toggleSociety(society.id)}\n                        />\n                        <Label htmlFor={society.id} className=\"cursor-pointer text-sm font-normal\">\n                          {society.name}\n                        </Label>\n                      </div>\n                    ))}\n                  </div>\n                </div>\n\n                {/* Furnishing Status Filter */}\n                <div className=\"space-y-3\">\n                  <Label className=\"font-semibold\">Furnishing Status</Label>\n                  <div className=\"grid grid-cols-2 gap-2\">\n                    {[\"Unfurnished\", \"Semi furnished\", \"furnished\", \"Fully furnished\"].map(\n                      (furnishing) => (\n                        <Button\n                          key={furnishing}\n                          variant={selectedFurnishing.includes(furnishing) ? \"default\" : \"outline\"}\n                          size=\"sm\"\n                          onClick={() => toggleFurnishing(furnishing)}\n                          className=\"text-xs\">\n                          {furnishing}\n                        </Button>\n                      )\n                    )}\n                  </div>\n                </div>\n              </CardContent>\n            </Card>\n          </aside>\n\n          {/* Property Listings */}\n          <main className=\"space-y-6\">\n            {filteredAndSortedProperties.length === 0 ? (\n              <Card>\n                <CardContent className=\"p-12 text-center\">\n                  <p className=\"text-muted-foreground text-lg\">\n                    No properties found matching your filters. Try adjusting your search criteria.\n                  </p>\n                </CardContent>\n              </Card>\n            ) : (\n              filteredAndSortedProperties.map((property) => (\n                <Card key={property.id} className=\"py-0 shadow-none\">\n                  <CardContent className=\"p-0\">\n                    <div className=\"grid md:grid-cols-[250px_1fr]\">\n                      {/* Property Image */}\n                      <div className=\"relative\">\n                        <img\n                          src={property.image || \"/placeholder.svg\"}\n                          alt={property.title}\n                          className=\"aspect-square h-full w-full object-cover md:rounded-l-lg\"\n                        />\n                        {property.verified && (\n                          <Badge className=\"absolute top-2 right-2 bg-white text-green-600 hover:bg-white\">\n                            <Check /> Verified\n                          </Badge>\n                        )}\n                      </div>\n\n                      {/* Property Details */}\n                      <div className=\"px-6 py-4\">\n                        <div className=\"space-y-4\">\n                          <div>\n                            <h3 className=\"text-foreground text-lg font-semibold\">\n                              {property.title}\n                            </h3>\n                            <p className=\"text-muted-foreground text-sm\">{property.location}</p>\n                          </div>\n\n                          <div className=\"grid grid-cols-2 gap-4 md:grid-cols-4\">\n                            <div>\n                              <p className=\"text-xl font-bold\">{formatPrice(property.price)}</p>\n                              <p className=\"text-muted-foreground text-xs\">\n                                ${property.pricePerSqFt}/sq.ft.\n                              </p>\n                            </div>\n                            <div>\n                              <p className=\"text-xl font-bold\">{property.area} sq.ft.</p>\n                              <p className=\"text-muted-foreground text-xs\">\n                                {property.areaDetails}\n                              </p>\n                            </div>\n                            <div>\n                              <p className=\"text-xl font-bold\">{property.bhk} BHK</p>\n                              <p className=\"text-muted-foreground text-xs\">\n                                {property.baths} Baths\n                              </p>\n                            </div>\n                          </div>\n\n                          <p className=\"text-muted-foreground line-clamp-2 text-sm\">\n                            {property.description}{\" \"}\n                            <span className=\"text-primary cursor-pointer\">More</span>\n                          </p>\n\n                          <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n                            <Button className=\"w-full sm:w-auto\">Contact Owner</Button>\n                            <div className=\"text-muted-foreground text-xs sm:text-right\">\n                              <p>\n                                Posted on {property.postedDate} by Owner {property.owner}\n                              </p>\n                            </div>\n                          </div>\n                        </div>\n                      </div>\n                    </div>\n                  </CardContent>\n                </Card>\n              ))\n            )}\n          </main>\n        </div>\n      </div>\n    </>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/property-filters.tsx"
    }
  ],
  "meta": {
    "isPro": true
  }
}