ROCKET WEDDING ENTERTAINMENT
  • Home
  • Team Availability
    • Meet The Team
  • Event Packages
  • MIXES
  • Contact Us!
import { useState, useMemo, useEffect } from "react"; const ADMIN_PASSWORD = "RocketEnt93"; const STORAGE_KEY = "vendor-directory-custom"; const baseVendors = [ { name: "Very Demure Events", category: "Coordinator", url: "https://www.instagram.com/verydemureevents_/" }, { name: "Stoic Events", category: "Coordinator", url: "https://www.instagram.com/stoic_events_coordinator/" }, { name: "Copper & Cove Events", category: "Coordinator", url: "https://www.instagram.com/copperandcoveevents/" }, { name: "Shelley Ann Events", category: "Planner", url: "https://www.instagram.com/shelleyannevents/" }, { name: "LOM Productions", category: "Planner", url: "https://www.instagram.com/lomproductions_weddings_events/" }, { name: "MK Designs", category: "Planner", url: "https://www.instagram.com/mk_designs__/" }, { name: "Your Party Besties", category: "Staffing", url: "https://www.instagram.com/yourpartybesties_llc" }, { name: "Cambia Luxe Events", category: "Guestbook", url: "https://www.instagram.com/cambrialuxeevents/" }, { name: "Absolute Comfort Limousine", category: "Transportation", url: "https://www.instagram.com/absolutecomfortlimousine/" }, { name: "Classic Charter", category: "Transportation", url: "https://www.instagram.com/classiccharter/" }, { name: "C&L Ranch", category: "Venue", url: "https://www.instagram.com/cl_ranch/" }, { name: "The Venue at Sombras", category: "Venue", url: "https://www.instagram.com/venueatsombras/" }, { name: "The Woodlands", category: "Venue", url: "https://www.instagram.com/thewoodlandsvisalia/" }, { name: "Springville Ranch", category: "Venue", url: "https://www.instagram.com/springvilleranch/" }, { name: "Grace Barn", category: "Venue", url: "https://www.instagram.com/gracebarn_krw/" }, { name: "Fresno Fields", category: "Venue", url: "https://www.instagram.com/wedgewood.fresnofields/" }, { name: "El Nido De Amor", category: "Venue", url: "https://www.instagram.com/el_nido_de_amor.venue/" }, { name: "Tuscan Garden Venue", category: "Venue", url: "https://www.instagram.com/tuscan.gardens.venue/" }, { name: "The Grand 1401", category: "Venue", url: "https://www.instagram.com/thegrand1401/" }, { name: "Weddings at The Grove", category: "Venue", url: "https://www.instagram.com/thegroveweddings/" }, { name: "Starlight Grove Events", category: "Venue", url: "https://www.instagram.com/starlightgroveevents/" }, { name: "Evergreen Island", category: "Venue", url: "https://www.instagram.com/evergreenislandtulare/" }, { name: "Chateau du Sureau", category: "Venue", url: "https://www.instagram.com/elderberryhouseevents/" }, { name: "Kingsburg Ranch", category: "Venue", url: "https://www.instagram.com/kingsburgranch/" }, { name: "Grangeville Oaks", category: "Venue", url: "https://www.instagram.com/grangevilleoaks/" }, { name: "Sunset Acres", category: "Venue", url: "https://www.instagram.com/thesunsetacrescentralvalley/" }, { name: "Sequoia Riverlands Trust", category: "Venue", url: "https://www.instagram.com/sequoiariverlands/" }, { name: "Riverfront Manor", category: "Venue", url: "https://www.instagram.com/riverfrontmanor/" }, { name: "The Nest Events & Rentals", category: "Decor & Rentals", url: "https://www.instagram.com/thenest_rentals/" }, { name: "Ari's Arches", category: "Decor & Rentals", url: "https://www.instagram.com/ari_arches/" }, { name: "Álvarez Balloons", category: "Decor & Rentals", url: "https://www.instagram.com/alvarezballoons" }, { name: "Creations by Regina", category: "Decor & Rentals", url: "https://www.instagram.com/creations.by.regina" }, { name: "CT Event Rental", category: "Decor & Rentals", url: "https://www.instagram.com/cteventrental/" }, { name: "Expo Event Productions", category: "Decor & Rentals", url: "https://www.instagram.com/expoeventproductions/" }, { name: "Brilliant Lounge", category: "Decor & Rentals", url: "https://www.instagram.com/brilliantlounge" }, { name: "K O Customs", category: "Decor & Rentals", url: "https://www.instagram.com/k_o_customs" }, { name: "Lux Balloons", category: "Decor & Rentals", url: "https://www.instagram.com/luxballoonss/" }, { name: "B & B Decorations", category: "Decor & Rentals", url: "https://www.instagram.com/bbdecorationss__" }, { name: "Blooming Event Decorator", category: "Decor & Rentals", url: "https://www.instagram.com/blooming_eventdecorator" }, { name: "Elegancia Decor", category: "Decor & Rentals", url: "https://www.instagram.com/elegancia_decor/" }, { name: "Modern Luxury Party Rentals", category: "Decor & Rentals", url: "https://www.instagram.com/mlprfresno" }, { name: "Lavish Decor", category: "Decor & Rentals", url: "https://www.instagram.com/lavishdecor559" }, { name: "Valley Decors", category: "Decor & Rentals", url: "https://www.instagram.com/valleydecors/" }, { name: "Protege Events", category: "Decor & Rentals", url: "https://www.instagram.com/protegeevents/" }, { name: "Prince J's Creations", category: "Decor & Rentals", url: "https://www.instagram.com/princejscreations11/" }, { name: "Light Up The Walls", category: "Decor & Rentals", url: "https://www.instagram.com/lightupthewalls/" }, { name: "Magaly's Decorations", category: "Decor & Rentals", url: "https://www.instagram.com/magalysdecorations/" }, { name: "A Rustic Affair", category: "Decor & Rentals", url: "https://www.instagram.com/arusticaffairrentals/" }, { name: "The Bubbles Photobooth", category: "Photo Booth", url: "https://www.instagram.com/thebubblesphotobooth" }, { name: "A Royal Photobooth", category: "Photo Booth", url: "https://www.instagram.com/aroyalphotoboothfresno" }, { name: "Two Little Doves", category: "Photo Booth", url: "https://www.instagram.com/twolittledoves/" }, { name: "PhoEver Photo Booth", category: "Photo Booth", url: "https://www.instagram.com/phoeverphotobooth/" }, { name: "Strike a Pose 360", category: "Photo Booth", url: "https://www.instagram.com/strike_a_pose360photobooths/" }, { name: "Luis Avalos Barber", category: "Beauty", url: "https://www.instagram.com/itsluis_thebarber/" }, { name: "makeupbyiza", category: "Beauty", url: "https://www.instagram.com/makeupbyiza/" }, { name: "MUA Mayhem", category: "Beauty", url: "https://www.instagram.com/mua.mayhem/" }, { name: "Jessie Arias Makeup", category: "Beauty", url: "https://www.instagram.com/jayarias/" }, { name: "Aubriana Diane", category: "Beauty", url: "https://www.instagram.com/beautynthebrush_" }, { name: "Paolas Bridal Beauty", category: "Beauty", url: "https://www.instagram.com/paolasbridalbeauty" }, { name: "Magda Alsamiri", category: "Beauty", url: "https://www.instagram.com/magdaalsamiri/" }, { name: "Glammed by Sophie", category: "Beauty", url: "https://www.instagram.com/glammedbysophie" }, { name: "Hair by Diana", category: "Beauty", url: "https://www.instagram.com/hairbyydiana_" }, { name: "Dañar Rodriguez", category: "Beauty", url: "https://www.instagram.com/styled_byynaee" }, { name: "Miki The Stylist", category: "Beauty", url: "https://www.instagram.com/mikithestylist/" }, { name: "Maricela Alcantar", category: "Beauty", url: "https://www.instagram.com/maricela_alcantar/" }, { name: "Artistry by Erendira", category: "Beauty", url: "https://www.instagram.com/artistrybyerendira/" }, { name: "beautybykirstenhaupt", category: "Beauty", url: "https://www.instagram.com/beautybykirstenhaupt/" }, { name: "Silvia Gonzalez", category: "Beauty", url: "https://www.instagram.com/slys_beauty_secret/" }, { name: "KYG Luxery Beauty", category: "Beauty", url: "https://www.instagram.com/kyg_luxerybeauty/" }, { name: "Fredo Hair & Makeup", category: "Beauty", url: "https://www.instagram.com/fredoo_" }, { name: "Foliage Fresno", category: "Beauty", url: "https://www.instagram.com/foliage_hairsalon/" }, { name: "Lux Nails by Ingrid", category: "Beauty", url: "https://www.instagram.com/luxnailsbyingrid_/" }, { name: "Annabelle's Bridal Boutique", category: "Attire", url: "https://www.instagram.com/annabellesbridal/" }, { name: "Ivory Bridal Boutique", category: "Attire", url: "https://www.instagram.com/ivory_bridalboutique/" }, { name: "What's Up Europe", category: "Attire", url: "https://www.instagram.com/whatsupeurope/" }, { name: "Love in Bloom Boutique", category: "Attire", url: "https://www.instagram.com/loveinbloombridal/" }, { name: "Madeleine's Bridal", category: "Attire", url: "https://www.instagram.com/madeleinesbridal/" }, { name: "Tux N Tails", category: "Attire", url: "https://www.instagram.com/tux_n_tails_visalia/" }, { name: "Tux N Ties", category: "Attire", url: "https://www.instagram.com/tux_n_ties_visalia/" }, { name: "Encore DJs", category: "DJ", url: "https://www.instagram.com/_encoredjs/" }, { name: "Mariachi Sol y Luna", category: "Mariachi & Banda", url: "https://www.instagram.com/mariachisolylunaoficial/" }, { name: "Mariachi La Purisima", category: "Mariachi & Banda", url: "https://www.instagram.com/mariachilapurisima" }, { name: "Mariachi Monarca", category: "Mariachi & Banda", url: "https://www.instagram.com/mariachi_monarca_/" }, { name: "Mariachi Alas De Jalisco", category: "Mariachi & Banda", url: "https://www.instagram.com/mariachi_alas_de_jalisco/" }, { name: "Mariachi Andaluz", category: "Mariachi & Banda", url: "https://www.instagram.com/mariachiandaluz/" }, { name: "Mariachi Show 559", category: "Mariachi & Banda", url: "https://www.instagram.com/mariachishow559" }, { name: "Banda REVO de Fresno", category: "Mariachi & Banda", url: "https://www.instagram.com/bandarevodefresno" }, { name: "Event Bartenders 559", category: "Bar & Drinks", url: "https://www.instagram.com/eventbartenders559/" }, { name: "Barra El Viejon", category: "Bar & Drinks", url: "https://www.instagram.com/barraelviejon" }, { name: "Solo Una Más Bartending", category: "Bar & Drinks", url: "https://www.instagram.com/solounamas_bartending" }, { name: "Destiny's Mobile Bar", category: "Bar & Drinks", url: "https://www.instagram.com/destinys.mobilebar" }, { name: "Tipsy Toes Club", category: "Bar & Drinks", url: "https://www.instagram.com/tipsytoesclub" }, { name: "Loly's Bar", category: "Bar & Drinks", url: "https://www.instagram.com/lolys_bar/" }, { name: "Mix & Sips", category: "Bar & Drinks", url: "https://www.instagram.com/mix_n_sip00/" }, { name: "El Mezcalero", category: "Bar & Drinks", url: "https://www.instagram.com/elmezcalero_/" }, { name: "Shaker Mami", category: "Bar & Drinks", url: "https://www.instagram.com/shaker_mamis_bartending/" }, { name: "Garnished Glass", category: "Bar & Drinks", url: "https://www.instagram.com/the.garnishedglass/" }, { name: "Booze & Brews Mobile Bar", category: "Bar & Drinks", url: "https://www.instagram.com/boozebrews.mobile/" }, { name: "Nightowl Mobile Bartending 559", category: "Bar & Drinks", url: "https://www.instagram.com/nightowlmobilebartending559/" }, { name: "Road Shakers Bar Rentals", category: "Bar & Drinks", url: "https://www.instagram.com/road_shakers_bar_rentals_/" }, { name: "Pour Me Mobile Bar", category: "Bar & Drinks", url: "https://www.instagram.com/pourme_mobilebar/" }, { name: "La Cantina Mobile Bar", category: "Bar & Drinks", url: "https://www.instagram.com/lacantinamobilebarllc" }, { name: "The Roaming Bar", category: "Bar & Drinks", url: "https://www.instagram.com/theroamingbar559" }, { name: "Sip Social Fresno", category: "Bar & Drinks", url: "https://www.instagram.com/sipsocialfresno/" }, { name: "Tap Truck CenCal", category: "Bar & Drinks", url: "https://www.instagram.com/taptruckcencal/" }, { name: "The Happy Camper", category: "Bar & Drinks", url: "https://www.instagram.com/thehappycampertrailer/" }, { name: "Boozy Belles", category: "Bar & Drinks", url: "https://www.instagram.com/theboozybelles/" }, { name: "The Bar Babee", category: "Bar & Drinks", url: "https://www.instagram.com/thebarbabee" }, { name: "Saddle Sips Saloon", category: "Bar & Drinks", url: "https://www.instagram.com/saddlesips/" }, { name: "Dirty Sodas Fresno", category: "Bar & Drinks", url: "https://www.instagram.com/sippinspecialtysodas/" }, { name: "yakimphotography", category: "Photography", url: "https://www.instagram.com/yakimphotography/" }, { name: "libtresphoto", category: "Photography", url: "https://www.instagram.com/libtresphoto/" }, { name: "Keith Hartman Photography", category: "Photography", url: "https://www.instagram.com/hartmanphoto/" }, { name: "Mykal Estrada Photography", category: "Photography", url: "https://www.instagram.com/mjephotography15" }, { name: "Erin Danae Photo", category: "Photography", url: "https://www.instagram.com/erindanaephoto/" }, { name: "Classy Rose Photography", category: "Photography", url: "https://www.instagram.com/classyrosephotography/" }, { name: "sagearaizaphoto", category: "Photography", url: "https://www.instagram.com/sagearaizaphoto/" }, { name: "cats.photography", category: "Photography", url: "https://www.instagram.com/cats.photography__/" }, { name: "Lomeli Images", category: "Photography", url: "https://www.instagram.com/lomeliimages/" }, { name: "Isaac's Eye Photography", category: "Photography", url: "https://www.instagram.com/isaacseye/" }, { name: "Graceful Glance Photography", category: "Photography", url: "https://www.instagram.com/gracefulglance/" }, { name: "Stills by Steven", category: "Photography", url: "https://www.instagram.com/stillsbysteven" }, { name: "Memories by Brianna", category: "Photography", url: "https://www.instagram.com/memoriesbybrianna" }, { name: "Víctor Photography", category: "Photography", url: "https://www.instagram.com/victor.photography" }, { name: "Rodríguez Media", category: "Photography", url: "https://www.instagram.com/rodriguez_media_" }, { name: "SB Photo Film", category: "Photography", url: "https://www.instagram.com/sbphotofilm/" }, { name: "Kapptured Photography", category: "Photography", url: "https://www.instagram.com/kappturedphotography/" }, { name: "Atro Photography", category: "Photography", url: "https://www.instagram.com/atrophotography_" }, { name: "Focal Point Studios", category: "Photography", url: "https://www.instagram.com/fps.photofilms/" }, { name: "Kerys Ross Photography", category: "Photography", url: "https://www.instagram.com/kerysrossphotography/" }, { name: "cinthiag.photo", category: "Photography", url: "https://www.instagram.com/cinthiag.photo/" }, { name: "Michelle Gunn Photography", category: "Photography", url: "https://www.instagram.com/michellegunnphoto/" }, { name: "Heather Nave Photography", category: "Photography", url: "https://www.instagram.com/heathernave.photography/" }, { name: "The Good Life Photography", category: "Photography", url: "https://www.instagram.com/the_good_life_photography/" }, { name: "Daniel Cang Photography", category: "Photography", url: "https://www.instagram.com/danielcangphotography/" }, { name: "sjyangproduction", category: "Videography", url: "https://www.instagram.com/sjyangproduction/" }, { name: "Vow and Tell", category: "Content Creator", url: "https://www.instagram.com/vowandtell/" }, { name: "Content by Liz", category: "Content Creator", url: "https://www.instagram.com/contentbyliz" }, { name: "Day of Diaries", category: "Content Creator", url: "https://www.instagram.com/dayofdiaries/" }, { name: "The Collective Catering", category: "Catering", url: "https://www.instagram.com/reveleventscatering/" }, { name: "Madres Tacos", category: "Catering", url: "https://www.instagram.com/madrestacos" }, { name: "Jack's Catering", category: "Catering", url: "https://www.instagram.com/jacks.catering/" }, { name: "Classic Catering 625", category: "Catering", url: "https://www.instagram.com/classiccatering625/" }, { name: "Carnitas La Fondita", category: "Catering", url: "https://www.instagram.com/carnitas_la_fondita/" }, { name: "Guisados Greicy", category: "Catering", url: "https://www.instagram.com/guisados.greicy/" }, { name: "La Huastequita Catering", category: "Catering", url: "https://www.instagram.com/la_huastequita_catering93" }, { name: "Los Amigos Fresno", category: "Catering", url: "https://www.instagram.com/losamigos559fresno" }, { name: "Mama J's Catering", category: "Catering", url: "https://www.instagram.com/mamajs_catering" }, { name: "Taqueria Don Orozco", category: "Catering", url: "https://www.instagram.com/taqueria_don_orozco_" }, { name: "Entre Cazuelas Porterville", category: "Catering", url: "https://www.instagram.com/entrecazuelas.porterville" }, { name: "Don Chuy's Taquiza", category: "Catering", url: "https://www.instagram.com/don_chuys_taquiza_autentica" }, { name: "Birria y Guisados Jamay", category: "Catering", url: "https://www.instagram.com/birriayguisadosjamay/" }, { name: "Tío Milios Tacos", category: "Catering", url: "https://www.instagram.com/tiomiliostacos" }, { name: "Tacos Bussin Mendota", category: "Catering", url: "https://www.instagram.com/tacosbussinmendota" }, { name: "La Cocinita de Cynthia", category: "Catering", url: "https://www.instagram.com/lacocinitadecynthia" }, { name: "La Victoria Catering", category: "Catering", url: "https://www.instagram.com/lavictoriacatering" }, { name: "Street Corner Tacos", category: "Catering", url: "https://www.instagram.com/street_corner_tacos_andmore/" }, { name: "Kahlo Salsa y Mas", category: "Catering", url: "https://www.instagram.com/kahlo_salsasymas" }, { name: "Penguin Tacos", category: "Catering", url: "https://www.instagram.com/penguin.tacos/" }, { name: "Los Amigos Restaurant", category: "Catering", url: "https://www.instagram.com/losamigosrestaurantellc/" }, { name: "Mi Ranchito", category: "Catering", url: "https://www.instagram.com/mi_ranchito_559/" }, { name: "Mi Sabor 559", category: "Catering", url: "https://www.instagram.com/mi_sabor559" }, { name: "La Cocina De Lichita", category: "Catering", url: "https://www.instagram.com/cocinadelichita/" }, { name: "Chef Guerito", category: "Catering", url: "https://www.instagram.com/chefguerito/" }, { name: "Yanez Catering", category: "Catering", url: "https://www.instagram.com/yanezcatering/" }, { name: "Big Bo's Smokehouse", category: "Catering", url: "https://www.instagram.com/big.bosbbq1/" }, { name: "Our Little Pizza Place", category: "Catering", url: "https://www.instagram.com/ourlittlepizzaplace/" }, { name: "Cocina Y Taqueria Esparza", category: "Catering", url: "https://www.instagram.com/cocina.esparza/" }, { name: "House of Floressence", category: "Florals", url: "https://www.instagram.com/houseoffloressence/" }, { name: "Costco Florals", category: "Florals", url: "https://www.costco.com/bulk-flowers.html" }, { name: "Rosie's Flower Shop", category: "Florals", url: "https://www.instagram.com/rosiesflowershopfresno" }, { name: "Ecstasy Flower Co", category: "Florals", url: "https://www.instagram.com/ecstasyflowerco" }, { name: "The Floral Fix", category: "Florals", url: "https://www.instagram.com/the_floral_fix" }, { name: "Melis Ramos Eternos", category: "Florals", url: "https://www.instagram.com/melisramoseternos" }, { name: "FleurElise Floral Studio", category: "Florals", url: "https://www.instagram.com/fleurelisestudio/" }, { name: "Kiku Floral", category: "Florals", url: "https://www.instagram.com/kikufloral/" }, { name: "Tropics by Design", category: "Florals", url: "https://www.instagram.com/tropicsbydesign/" }, { name: "Blooming Moments", category: "Florals", url: "https://www.instagram.com/bloomingmomentsllc/" }, { name: "Lily and Liv", category: "Florals", url: "https://www.instagram.com/lilyandliv.co/" }, { name: "Ampersand Ice Cream", category: "Desserts", url: "https://www.instagram.com/ampersandicecream/" }, { name: "Goodies Cookies", category: "Desserts", url: "https://www.instagram.com/goodiescookiesvisalia/" }, { name: "Con Besos", category: "Desserts", url: "https://www.instagram.com/conbesos/" }, { name: "The Treat Bar", category: "Desserts", url: "https://www.instagram.com/the.treat.bar_/" }, { name: "Mini Pancakes by Chilla", category: "Desserts", url: "https://www.instagram.com/minipancakes_bychilla" }, { name: "Sweets by Mony", category: "Desserts", url: "https://www.instagram.com/sweetsbymonyy/" }, { name: "Bellas Mini Pancakes", category: "Desserts", url: "https://www.instagram.com/bellasminipancakes" }, { name: "Angelina's Sugar Cookies", category: "Desserts", url: "https://www.instagram.com/angelinas_sugarcookies" }, { name: "Hecho Con Amor Bakery", category: "Desserts", url: "https://www.instagram.com/h.c.a.bakery/" }, { name: "Bake It Mine", category: "Desserts", url: "https://www.instagram.com/bakeitmine__/" }, { name: "susan.g_creations", category: "Desserts", url: "https://www.instagram.com/susan.g_creations/" }, { name: "Aayanah's Bakehouse", category: "Desserts", url: "https://www.instagram.com/aayanahs_bakehouse" }, { name: "Bedwell's Bakes", category: "Desserts", url: "https://www.instagram.com/bedwells_bakes/" }, { name: "Bebe the Baker", category: "Desserts", url: "https://www.instagram.com/bebe_the_baker/" }, { name: "Yazzys Mini Bar", category: "Desserts", url: "https://www.instagram.com/yazzysminibar/" }, { name: "Leon's Snack Bar", category: "Desserts", url: "https://www.instagram.com/leons_snackbar/" }, { name: "Crazy Daizy", category: "Charcuterie", url: "https://www.instagram.com/grazydaizy" }, { name: "Graze Craze Visalia", category: "Charcuterie", url: "https://www.instagram.com/visaliagrazecraze/" }, { name: "Hosanna's Coffee & Matcha", category: "Coffee", url: "https://www.instagram.com/hosannasofficial/" }, { name: "The Brew Coffee & Bakery", category: "Coffee", url: "https://www.instagram.com/thebrewcoffeeandbakery/" }, { name: "D Rose Art Flower Preservation", category: "Flower Preservation", url: "https://www.instagram.com/mrs_d_rose/" }, ]; const categoryEmojis = { "Coordinator": "□", "Planner": "□️", "Staffing": "□", "Guestbook": "□", "Transportation": "□", "Venue": "□", "Decor & Rentals": "✨", "Photo Booth": "□", "Beauty": "□", "Attire": "□", "DJ": "□", "Mariachi & Banda": "□", "Bar & Drinks": "□", "Photography": "□", "Videography": "□", "Content Creator": "□", "Catering": "□️", "Florals": "□", "Desserts": "□", "Charcuterie": "□", "Coffee": "☕", "Flower Preservation": "□", }; const categoryColors = { "Coordinator": "#c8a97e", "Planner": "#c8a97e", "Staffing": "#b8956a", "Guestbook": "#d4b896", "Transportation": "#8a7560", "Venue": "#7d5a3c", "Decor & Rentals": "#c17f5b", "Photo Booth": "#a0522d", "Beauty": "#c9876b", "Attire": "#8b6b4a", "DJ": "#5c4033", "Mariachi & Banda": "#9e6b4a", "Bar & Drinks": "#7b3f20", "Photography": "#6b4226", "Videography": "#5a3520", "Content Creator": "#8b5e3c", "Catering": "#a0522d", "Florals": "#b87333", "Desserts": "#d4956a", "Charcuterie": "#c4a882", "Coffee": "#6f4e37", "Flower Preservation": "#c47c5a", }; export default function VendorDirectory() { const [activeCategory, setActiveCategory] = useState("All"); const [search, setSearch] = useState(""); const [customVendors, setCustomVendors] = useState([]); const [adminOpen, setAdminOpen] = useState(false); const [adminUnlocked, setAdminUnlocked] = useState(false); const [pwInput, setPwInput] = useState(""); const [pwError, setPwError] = useState(false); const [form, setForm] = useState({ name: "", category: "", customCategory: "", url: "" }); const [saveMsg, setSaveMsg] = useState(""); const [deleteConfirm, setDeleteConfirm] = useState(null); // Load saved vendors on mount useEffect(() => { const load = async () => { try { const result = await window.storage.get(STORAGE_KEY); if (result && result.value) { setCustomVendors(JSON.parse(result.value)); } } catch (e) { // No saved vendors yet } }; load(); }, []); const allVendors = useMemo(() => [...baseVendors, ...customVendors], [customVendors]); const categories = useMemo(() => { const cats = [...new Set(allVendors.map(v => v.category))]; return ["All", ...cats]; }, [allVendors]); const filtered = useMemo(() => { return allVendors.filter(v => { const matchCat = activeCategory === "All" || v.category === activeCategory; const matchSearch = v.name.toLowerCase().includes(search.toLowerCase()) || v.category.toLowerCase().includes(search.toLowerCase()); return matchCat && matchSearch; }); }, [allVendors, activeCategory, search]); const grouped = useMemo(() => { if (activeCategory !== "All" || search) return null; const groups = {}; filtered.forEach(v => { if (!groups[v.category]) groups[v.category] = []; groups[v.category].push(v); }); return groups; }, [filtered, activeCategory, search]); const handleLogin = () => { if (pwInput === ADMIN_PASSWORD) { setAdminUnlocked(true); setPwError(false); setPwInput(""); } else { setPwError(true); setPwInput(""); } }; const handleAddVendor = async () => { const finalCategory = form.category === "__new__" ? form.customCategory.trim() : form.category; if (!form.name.trim() || !finalCategory) return; const newVendor = { name: form.name.trim(), category: finalCategory, url: form.url.trim() || null, custom: true, }; const updated = [...customVendors, newVendor]; setCustomVendors(updated); try { await window.storage.set(STORAGE_KEY, JSON.stringify(updated)); setSaveMsg("✓ Vendor saved!"); setTimeout(() => setSaveMsg(""), 3000); } catch (e) { setSaveMsg("Error saving -- try again."); } setForm({ name: "", category: "", customCategory: "", url: "" }); }; const handleDelete = async (vendorName) => { const updated = customVendors.filter(v => v.name !== vendorName); setCustomVendors(updated); try { await window.storage.set(STORAGE_KEY, JSON.stringify(updated)); } catch (e) {} setDeleteConfirm(null); }; const existingCategories = [...new Set(allVendors.map(v => v.category))].sort(); return (
{/* Header */}

559 · Central Valley

Trusted Vendor Directory

Vendors we know, love, and stand behind — hand-curated for Central Valley celebrations.

{/* Search */}
setSearch(e.target.value)} />
{/* Category filters */}
{categories.map(cat => ( ))}
{/* Count */}
{filtered.length} vendors
{/* Grouped view */} {grouped ? (
{Object.entries(grouped).map(([cat, items]) => (
{categoryEmojis[cat] || "□"}

{cat}

{items.length}
{items.map(v => ( setDeleteConfirm(v.name)} /> ))}
))}
) : (
{filtered.length === 0 ? (
No vendors found for "{search}"
) : filtered.map(v => ( setDeleteConfirm(v.name)} /> ))}
)}
{/* Admin Modal */} {adminOpen && (
{ if (e.target === e.currentTarget) { setAdminOpen(false); setAdminUnlocked(false); setPwError(false); }}}>
{!adminUnlocked ? ( <>

Admin Access

Enter your password to manage vendors.

{ setPwInput(e.target.value); setPwError(false); }} onKeyDown={e => e.key === "Enter" && handleLogin()} autoFocus /> {pwError &&

Incorrect password. Try again.

}
) : ( <>

Add a Vendor

New vendors save automatically.

setForm(f => ({ ...f, name: e.target.value }))} />
{form.category === "__new__" && (
setForm(f => ({ ...f, customCategory: e.target.value }))} />
)}
setForm(f => ({ ...f, url: e.target.value }))} />
{saveMsg && (

{saveMsg}

)} {/* Custom vendor list */} {customVendors.length > 0 && (

Your Added Vendors ({customVendors.length})

{customVendors.map(v => (

{v.name}

{v.category}

))}
)} )}
)} {/* Delete confirm */} {deleteConfirm && (
{ if (e.target === e.currentTarget) setDeleteConfirm(null); }}>

□️

Remove Vendor?

This will remove "{deleteConfirm}" from the directory.

)}
); } function VendorCard({ vendor, color, isAdmin, onDelete }) { return (

{vendor.name} {vendor.custom && ✦ new}

{vendor.category}

{vendor.url && ( Visit ↗ )} {isAdmin && vendor.custom && ( )}
);
559 Trusted Vendor Directory

559 · Central Valley

Trusted Vendor Directory

Vendors we know, love, and stand behind — hand-curated for Central Valley celebrations.

0 vendors

Admin Access

Enter your password to manage vendors.

Incorrect password. Try again.

Add a Vendor

Saved vendors appear in the directory instantly.

✏️ Editing vendor

□️

Remove Vendor?

  • Home
  • Team Availability
    • Meet The Team
  • Event Packages
  • MIXES
  • Contact Us!