zeroed-some/localroast / 9dd5de7

Browse files

fix roast reversion

Authored by espadonne
SHA
9dd5de7e589f7b5454b1da96422d202f3ffa66b7
Parents
c1a09e1
Tree
3c779c5

2 changed files

StatusFile+-
M src/App.js 63 80
M src/services/roastService.js 71 16
src/App.jsmodified
@@ -1,40 +1,11 @@
1
-// src/App.js - Complete working app in one file for quick testing
1
+// src/App.js - Complete working app with fixes
22
 import React, { useState } from 'react';
33
 import './App.css';
4
-
5
-// Mini roast database for testing
6
-const roastDatabase = {
7
-  'New York': [
8
-    "NYC? Let me guess, you've mentioned you're from New York within 5 minutes of every conversation you've ever had.",
9
-    "From NYC? Cool, how's that superiority complex and vitamin D deficiency working out?",
10
-    "New York City: Where everyone walks fast to nowhere important and calls it ambition."
11
-  ],
12
-  'California': [
13
-    "California? How's that $8 gas and $15 avocado toast treating you?",
14
-    "Oh, you're from California? Which wellness trend are you pretending changed your life this week?",
15
-    "California: Come for the weather, stay because you can't afford to leave."
16
-  ],
17
-  'Texas': [
18
-    "Texas? Everything's bigger there, especially the egos and the power grid failures.",
19
-    "From Texas? Let me guess, you've already mentioned how big your state is three times today.",
20
-    "Texas: Where 105°F is 'nice weather' and a light dusting of snow shuts down civilization."
21
-  ],
22
-  'Virginia': [
23
-    "Virginia? The state that can't decide if it's the South or just South of Maryland.",
24
-    "From Virginia? Home of 'Virginia is for Lovers' - because you need a slogan when you have no personality.",
25
-    "Virginia: Where Northern Virginia pretends it's DC and the rest pretends it's still 1865.",
26
-    "Oh, Virginia? The state whose biggest achievement is being close to somewhere important.",
27
-    "Virginia: Where everyone works for the government but swears they're a 'small government conservative'."
28
-  ],
29
-  'default': [
30
-    "Your location is so irrelevant, even Google Maps just shrugs.",
31
-    "From there? I'd roast your hometown but it would require me to care about it first.",
32
-    "Your area is so forgettable, even this roast generator had nothing prepared."
33
-  ]
34
-};
4
+import { getRoastsForLocation } from './services/roastService';
355
 
366
 function App() {
377
   const [location, setLocation] = useState(null);
8
+  const [locationObj, setLocationObj] = useState(null); // Store the structured object separately
389
   const [currentRoast, setCurrentRoast] = useState(null);
3910
   const [loading, setLoading] = useState(false);
4011
   const [error, setError] = useState(null);
@@ -50,20 +21,35 @@ function App() {
5021
         const response = await fetch('https://ipapi.co/json/');
5122
         const data = await response.json();
5223
         
53
-        // Build location string from most specific to least specific
24
+        // Build location object from API response
25
+        const locationObj = {
26
+          city: data.city || null,
27
+          state: data.region || null,
28
+          country: data.country_name || null
29
+        };
30
+        
31
+        // Create display string
5432
         let locationStr = '';
5533
         if (data.city) {
5634
           locationStr = data.city;
5735
           if (data.region) {
58
-            locationStr = data.region; // Use state/region as primary identifier
36
+            locationStr += `, ${data.region}`;
37
+          }
38
+          if (data.country_name) {
39
+            locationStr += `, ${data.country_name}`;
5940
           }
6041
         } else if (data.region) {
6142
           locationStr = data.region;
43
+          if (data.country_name) {
44
+            locationStr += `, ${data.country_name}`;
45
+          }
6246
         } else if (data.country_name) {
6347
           locationStr = data.country_name;
6448
         }
6549
         
66
-        handleLocationFound(locationStr || 'Unknown');
50
+        setLocation(locationStr || 'Unknown');
51
+        setLocationObj(locationObj); // Store the structured object
52
+        handleLocationFound(locationObj);
6753
       } catch (err) {
6854
         setError("Couldn't detect location. Try entering manually!");
6955
         setLoading(false);
@@ -75,68 +61,65 @@ function App() {
7561
   };
7662
 
7763
   const handleLocationFound = (loc) => {
78
-    setLocation(loc);
79
-    
80
-    // Normalize the location for database lookup
81
-    const normalizedLoc = loc.trim()
82
-      .split(' ')
83
-      .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
84
-      .join(' ');
85
-    
86
-    // Try exact match first, then try just the first word (for "Los Angeles, California" -> "California")
87
-    let roasts = roastDatabase[normalizedLoc];
88
-    
89
-    if (!roasts && loc.includes(',')) {
90
-      // Try the state/country part after the comma
91
-      const parts = loc.split(',');
92
-      const statePart = parts[1].trim()
93
-        .split(' ')
94
-        .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
95
-        .join(' ');
96
-      roasts = roastDatabase[statePart];
97
-    }
64
+    // Parse the location string if needed
65
+    let parsedLocationObj = { city: null, state: null, country: null };
9866
     
99
-    if (!roasts) {
100
-      // Try some common variations
101
-      const variations = {
102
-        'Ny': 'New York',
103
-        'Nyc': 'New York',
104
-        'La': 'California',
105
-        'Los Angeles': 'California',
106
-        'San Francisco': 'California',
107
-        'Sf': 'California',
108
-        'Tx': 'Texas',
109
-        'Va': 'Virginia',
110
-        'Cali': 'California'
111
-      };
67
+    if (typeof loc === 'string') {
68
+      // If it's a string, try to parse it
69
+      const parts = loc.split(',').map(p => p.trim());
11270
       
113
-      const variation = variations[normalizedLoc];
114
-      if (variation) {
115
-        roasts = roastDatabase[variation];
71
+      if (parts.length === 1) {
72
+        // Could be city, state, or country
73
+        parsedLocationObj.city = parts[0];
74
+      } else if (parts.length === 2) {
75
+        // Likely "City, State" or "City, Country"
76
+        parsedLocationObj.city = parts[0];
77
+        parsedLocationObj.state = parts[1];
78
+      } else if (parts.length >= 3) {
79
+        // "City, State, Country" format
80
+        parsedLocationObj.city = parts[0];
81
+        parsedLocationObj.state = parts[1];
82
+        parsedLocationObj.country = parts[2];
11683
       }
84
+    } else if (typeof loc === 'object') {
85
+      // If it's already an object, use it directly
86
+      parsedLocationObj = loc;
11787
     }
11888
     
119
-    // Default to generic roasts if nothing found
120
-    roasts = roasts || roastDatabase.default;
89
+    // Store the parsed object for reuse
90
+    setLocationObj(parsedLocationObj);
91
+    
92
+    // Get roasts using the service
93
+    const roasts = getRoastsForLocation(parsedLocationObj);
94
+    
95
+    if (roasts.length > 0) {
96
+      const randomRoast = roasts[Math.floor(Math.random() * roasts.length)];
97
+      setCurrentRoast(randomRoast);
98
+    } else {
99
+      setCurrentRoast("Your location is so irrelevant, even our roast database gave up.");
100
+    }
121101
     
122
-    const randomRoast = roasts[Math.floor(Math.random() * roasts.length)];
123
-    setCurrentRoast(randomRoast);
124102
     setLoading(false);
125103
   };
126104
 
127105
   const handleManualSubmit = (e) => {
128106
     e.preventDefault();
129107
     if (manualInput.trim()) {
130
-      handleLocationFound(manualInput.trim());
108
+      const inputLocation = manualInput.trim();
109
+      setLocation(inputLocation);
110
+      handleLocationFound(inputLocation);
131111
       setManualInput('');
132112
     }
133113
   };
134114
 
135115
   const getAnotherRoast = () => {
136
-    if (location) {
137
-      const roasts = roastDatabase[location] || roastDatabase.default;
138
-      const randomRoast = roasts[Math.floor(Math.random() * roasts.length)];
139
-      setCurrentRoast(randomRoast);
116
+    if (locationObj) {
117
+      // Use the stored location object instead of parsing the display string
118
+      const roasts = getRoastsForLocation(locationObj);
119
+      if (roasts.length > 0) {
120
+        const randomRoast = roasts[Math.floor(Math.random() * roasts.length)];
121
+        setCurrentRoast(randomRoast);
122
+      }
140123
     }
141124
   };
142125
 
src/services/roastService.jsmodified
@@ -6,32 +6,50 @@ export const getRoastsForLocation = (location) => {
66
   let roasts = [];
77
   const { city, state, country } = location;
88
   
9
-  // Normalize location names
10
-  const cityLower = city?.toLowerCase().replace(/\s+/g, '_');
11
-  const stateLower = state?.toLowerCase().replace(/\s+/g, '_');
12
-  const countryLower = country?.toLowerCase().replace(/\s+/g, '_');
13
-  
14
-  // Check for city-specific roasts
15
-  if (cityLower) {
16
-    // Look through all states for this city
17
-    for (const [stateKey, stateData] of Object.entries(roastDatabase)) {
18
-      if (stateData[cityLower]) {
19
-        roasts = roasts.concat(stateData[cityLower]);
9
+  // Normalize location names - convert spaces to underscores and lowercase
10
+  const normalizeString = (str) => str?.toLowerCase().replace(/\s+/g, '_').replace(/[^\w_]/g, '');
11
+  
12
+  const cityNormalized = normalizeString(city);
13
+  const stateNormalized = normalizeString(state);
14
+  const countryNormalized = normalizeString(country);
15
+  
16
+  // If only city is provided, search through all states/countries for this city
17
+  if (cityNormalized && !stateNormalized && !countryNormalized) {
18
+    for (const [regionKey, regionData] of Object.entries(roastDatabase)) {
19
+      // Skip the 'default' entry
20
+      if (regionKey === 'default') continue;
21
+      
22
+      // Check if this region has the city
23
+      if (regionData[cityNormalized]) {
24
+        roasts = roasts.concat(regionData[cityNormalized]);
25
+        // Also add some generic roasts from the parent region
26
+        if (regionData.generic) {
27
+          roasts = roasts.concat(regionData.generic.slice(0, 2)); // Add a couple generic ones
28
+        }
29
+        break; // Found the city, stop searching
2030
       }
2131
     }
2232
   }
2333
   
24
-  // Check for state/region roasts
25
-  if (stateLower && roastDatabase[stateLower]?.generic) {
26
-    roasts = roasts.concat(roastDatabase[stateLower].generic);
34
+  // If we have state/country info, use it for more specific matching
35
+  if (stateNormalized && roastDatabase[stateNormalized]) {
36
+    // Check for city-specific roasts within the state
37
+    if (cityNormalized && roastDatabase[stateNormalized][cityNormalized]) {
38
+      roasts = roasts.concat(roastDatabase[stateNormalized][cityNormalized]);
39
+    }
40
+    // Add state generic roasts
41
+    if (roastDatabase[stateNormalized].generic) {
42
+      roasts = roasts.concat(roastDatabase[stateNormalized].generic);
43
+    }
2744
   }
2845
   
2946
   // Check for country roasts
30
-  if (countryLower) {
47
+  if (countryNormalized) {
3148
     const countryMappings = {
3249
       'united_states': 'usa',
3350
       'united_states_of_america': 'usa',
3451
       'us': 'usa',
52
+      'america': 'usa',
3553
       'united_kingdom': 'uk',
3654
       'great_britain': 'uk',
3755
       'england': 'uk',
@@ -40,12 +58,49 @@ export const getRoastsForLocation = (location) => {
4058
       'northern_ireland': 'uk'
4159
     };
4260
     
43
-    const countryKey = countryMappings[countryLower] || countryLower;
61
+    const countryKey = countryMappings[countryNormalized] || countryNormalized;
4462
     if (roastDatabase[countryKey]?.generic) {
4563
       roasts = roasts.concat(roastDatabase[countryKey].generic);
4664
     }
4765
   }
4866
   
67
+  // Special handling for common state abbreviations
68
+  const stateAbbreviations = {
69
+    'ny': 'newyork',
70
+    'nyc': 'newyork',
71
+    'ca': 'california',
72
+    'tx': 'texas',
73
+    'fl': 'florida',
74
+    'il': 'illinois',
75
+    'pa': 'pennsylvania',
76
+    'oh': 'ohio',
77
+    'mi': 'michigan',
78
+    'ga': 'georgia',
79
+    'nc': 'north_carolina',
80
+    'va': 'virginia',
81
+    'ma': 'massachusetts',
82
+    'az': 'arizona',
83
+    'wa': 'washington',
84
+    'co': 'colorado',
85
+    'or': 'oregon',
86
+    'nv': 'nevada',
87
+    'la': 'louisiana',
88
+    'wi': 'wisconsin'
89
+  };
90
+  
91
+  // If no roasts found yet, check if the input matches a state abbreviation
92
+  if (roasts.length === 0 && cityNormalized) {
93
+    const stateKey = stateAbbreviations[cityNormalized];
94
+    if (stateKey && roastDatabase[stateKey]?.generic) {
95
+      roasts = roasts.concat(roastDatabase[stateKey].generic);
96
+    }
97
+  }
98
+  
99
+  // If still no roasts, check if the city input might actually be a state name
100
+  if (roasts.length === 0 && cityNormalized && roastDatabase[cityNormalized]?.generic) {
101
+    roasts = roasts.concat(roastDatabase[cityNormalized].generic);
102
+  }
103
+  
49104
   // If no specific roasts found, use defaults
50105
   if (roasts.length === 0) {
51106
     roasts = roastDatabase.default || [];