@@ -30,14 +30,6 @@ type Landmark = {
30
30
isOpen : boolean
31
31
} ;
32
32
33
- const MINERALS = [ 'Iron' , 'Copper' , 'Coal' , 'Nickel' ] ;
34
-
35
- const LANDMARKS : Landmark [ ] = [
36
- { id : '1' , name : 'Base Camp' , description : 'Main operations center for the mining colony.' , position : { x : 10 , y : 10 } , isOpen : false } ,
37
- { id : '2' , name : 'Power Plant' , description : 'Generates power for the entire mining operation.' , position : { x : 80 , y : 30 } , isOpen : false } ,
38
- { id : '3' , name : 'Research Lab' , description : 'Conducts studies on Martian geology and potential life.' , position : { x : 30 , y : 70 } , isOpen : false } ,
39
- ] ;
40
-
41
33
export function MiningComponentComponent ( ) {
42
34
const supabase = useSupabaseClient ( ) ;
43
35
const session = useSession ( ) ;
@@ -51,67 +43,149 @@ export function MiningComponentComponent() {
51
43
const [ inventory , setInventory ] = useState < InventoryItem [ ] > ( [ ] )
52
44
const [ isMining , setIsMining ] = useState ( false )
53
45
const [ activeMap , setActiveMap ] = useState < '2D' | '3D' > ( '2D' )
54
- const [ landmarks , setLandmarks ] = useState < Landmark [ ] > ( LANDMARKS ) ;
46
+ const [ landmarks , setLandmarks ] = useState < Landmark [ ] > ( [ ] ) ;
55
47
56
48
useEffect ( ( ) => {
57
- const fetchDeposits = async ( ) => {
49
+ const fetchLandmarks = async ( ) => {
58
50
if ( ! session ?. user ?. id || ! activePlanet ?. id ) {
59
51
console . error ( "User or activePlanet is undefined." ) ;
60
52
return ;
61
53
}
62
54
63
- const { data, error } = await supabase
55
+ // Fetch inventory from Supabase
56
+ const { data : inventoryData , error : inventoryError } = await supabase
57
+ . from ( "inventory" )
58
+ . select ( "id, item, quantity" )
59
+ . eq ( "owner" , session . user . id )
60
+ . eq ( "anomaly" , activePlanet . id )
61
+ . gt ( "quantity" , 0 ) ;
62
+
63
+ if ( inventoryError ) {
64
+ console . error ( "Error fetching inventory:" , inventoryError ) ;
65
+ return ;
66
+ }
67
+
68
+ // Fetch all item details from API
69
+ const res = await fetch ( '/api/gameplay/inventory' ) ;
70
+ const items = await res . json ( ) ;
71
+
72
+ // Filter for structures and map to landmarks
73
+ const structures = inventoryData
74
+ ?. filter ( ( inventoryItem ) =>
75
+ items . some (
76
+ ( item : { id : any ; ItemCategory : string } ) =>
77
+ item . id === inventoryItem . item && item . ItemCategory === "Structure"
78
+ )
79
+ )
80
+ . map ( ( inventoryItem ) => {
81
+ const itemDetails = items . find (
82
+ ( item : { id : any } ) => item . id === inventoryItem . item
83
+ ) ;
84
+
85
+ return {
86
+ id : inventoryItem . id . toString ( ) ,
87
+ name : itemDetails ?. name || "Unknown" ,
88
+ description : itemDetails ?. description || "No description available" ,
89
+ position : itemDetails ?. position || { x : Math . random ( ) * 100 , y : Math . random ( ) * 100 } , // Default to random position
90
+ isOpen : false ,
91
+ } ;
92
+ } ) ;
93
+
94
+ setLandmarks ( structures || [ ] ) ;
95
+ } ;
96
+
97
+ fetchLandmarks ( ) ;
98
+ } , [ session , activePlanet , supabase ] ) ;
99
+
100
+ useEffect ( ( ) => {
101
+ const fetchDepositsAndInventory = async ( ) => {
102
+ if ( ! session ?. user ?. id || ! activePlanet ?. id ) {
103
+ console . error ( "User or activePlanet is undefined." ) ;
104
+ return ;
105
+ }
106
+
107
+ // Fetch deposits
108
+ const { data : deposits , error : depositsError } = await supabase
64
109
. from ( "mineralDeposits" )
65
- . select ( 'id, mineralconfiguration' )
66
- . eq ( 'owner' , session ?. user . id )
67
- . eq ( 'anomaly' , activePlanet ?. id )
68
- . limit ( 4 ) ;
110
+ . select ( "id, mineralconfiguration" )
111
+ . eq ( "owner" , session ?. user . id )
112
+ . eq ( "anomaly" , activePlanet ?. id ) ;
69
113
70
- if ( error ) {
71
- console . error ( "Error fetching mineral deposits:" , error ) ;
114
+ if ( depositsError ) {
115
+ console . error ( "Error fetching mineral deposits:" , depositsError ) ;
72
116
return ;
73
117
}
74
118
75
- const formattedDeposits = data ?. map ( ( deposit ) => ( {
76
- id : deposit . id ,
119
+ const formattedDeposits = deposits ?. map ( ( deposit , index ) => ( {
120
+ id : ` ${ deposit . id } - ${ index } ` , // Ensure uniqueness
77
121
name : deposit . mineralconfiguration . mineral || "Unknown" ,
78
122
mineral : deposit . mineralconfiguration . mineral || "Unknown" ,
79
- amount : deposit . mineralconfiguration . quantity || 0 , // Use 'amount'
123
+ amount : deposit . mineralconfiguration . quantity || 0 ,
80
124
icon_url : deposit . mineralconfiguration . icon_url || "" ,
81
125
level : deposit . mineralconfiguration . level || 1 ,
82
126
uses : deposit . mineralconfiguration . uses || [ ] ,
83
127
position : deposit . mineralconfiguration . position || { x : 50 , y : 50 } ,
84
128
} ) ) ;
85
129
86
130
setMineralDeposits ( formattedDeposits || [ ] ) ;
131
+
132
+ // Fetch inventory and filter structures
133
+ const { data : inventoryData , error : inventoryError } = await supabase
134
+ . from ( "inventory" )
135
+ . select ( "id, item, quantity" )
136
+ . eq ( "owner" , session ?. user . id )
137
+ . eq ( "anomaly" , activePlanet ?. id )
138
+ . gt ( "quantity" , 0 ) ;
139
+
140
+ if ( inventoryError ) {
141
+ console . error ( "Error fetching inventory:" , inventoryError ) ;
142
+ return ;
143
+ }
144
+
145
+ // Fetch all items from the API route
146
+ const res = await fetch ( '/api/gameplay/inventory' ) ;
147
+ const items = await res . json ( ) ;
148
+
149
+ // Filter inventory to include only items of type "Structure"
150
+ const structures = inventoryData
151
+ ?. filter ( ( inventoryItem ) =>
152
+ items . some (
153
+ ( item : { id : any ; ItemCategory : string ; } ) =>
154
+ item . id === inventoryItem . item &&
155
+ item . ItemCategory === "Structure"
156
+ )
157
+ )
158
+ . map ( ( inventoryItem ) => {
159
+ const itemDetails = items . find (
160
+ ( item : { id : any ; } ) => item . id === inventoryItem . item
161
+ ) ;
162
+ return {
163
+ id : inventoryItem . id . toString ( ) ,
164
+ name : itemDetails ?. name || "Unknown" ,
165
+ description : itemDetails ?. description || "" ,
166
+ amount : inventoryItem . quantity || 0 ,
167
+ icon_url : itemDetails ?. icon_url || "" ,
168
+ locationType : itemDetails ?. locationType || "Unknown" ,
169
+ } ;
170
+ } ) ;
171
+
172
+ setInventory ( structures || [ ] ) ;
173
+ setRover ( {
174
+ id : "1" ,
175
+ name : "Mars Rover" ,
176
+ speed : 15 ,
177
+ efficiency : 0.8 ,
178
+ miningLevel : 2 ,
179
+ } ) ;
87
180
} ;
88
181
89
- fetchDeposits ( ) ;
90
- } , [ session , activePlanet , supabase ] ) ;
91
-
92
- // useEffect(() => {
93
- // const generateDeposits = () => {
94
- // const deposits: MineralDeposit[] = []
95
- // for (let i = 0; i < 4; i++) {
96
- // const mineral = MINERALS[Math.floor(Math.random() * MINERALS.length)]
97
- // deposits.push({
98
- // id: `${i + 1}`,
99
- // name: mineral,
100
- // amount: Math.floor(Math.random() * 500) + 500,
101
- // position: { x: Math.random() * 80 + 10, y: Math.random() * 80 + 10 },
102
- // })
103
- // }
104
- // return deposits
105
- // }
106
-
107
- // setMineralDeposits(generateDeposits())
108
- // setRover({ id: '1', name: 'Mars Rover', speed: 15, efficiency: 0.8, miningLevel: 2 })
109
- // setInventory(MINERALS.map((mineral, index) => ({ id: `${index + 1}`, name: mineral, amount: 0 })))
110
- // }, [])
111
-
182
+ fetchDepositsAndInventory ( ) ;
183
+ } , [ session , activePlanet , supabase ] ) ;
184
+
112
185
const handleDepositSelect = ( deposit : MineralDeposit ) => {
113
- setSelectedDeposit ( deposit )
114
- }
186
+ console . log ( "Deposit selected:" , deposit ) ; // Debugging line
187
+ setSelectedDeposit ( deposit ) ;
188
+ } ;
115
189
116
190
const handleStartMining = ( ) => {
117
191
if ( selectedDeposit && rover ) {
@@ -138,9 +212,9 @@ export function MiningComponentComponent() {
138
212
setTimeout ( ( ) => {
139
213
setRoverPosition ( { x : 5 , y : 5 } ) ; // Return to base
140
214
setIsMining ( false ) ;
141
- updateInventory ( selectedDeposit . name , 50 ) ; // Add mined resources to inventory
215
+ updateInventory ( selectedDeposit . name , 50 ) ; // Update Supabase with mined resources
142
216
setSelectedDeposit ( null ) ; // Reset selected deposit
143
- } , 5000 ) ; // 5 seconds at deposit
217
+ } , 5000 ) ; // 5 seconds at deposit
144
218
}
145
219
} ;
146
220
@@ -150,21 +224,86 @@ export function MiningComponentComponent() {
150
224
}
151
225
} ;
152
226
153
- const updateInventory = ( resourceName : string , amount : number ) => {
154
- setInventory ( prev => prev . map ( item =>
155
- item . name === resourceName ? { ...item , amount : item . amount + amount } : item
156
- ) )
157
- }
227
+ const updateInventory = async ( resourceName : string , minedAmount : number ) => {
228
+ if ( ! session ?. user ?. id || ! activePlanet ?. id ) {
229
+ console . error ( "User or activePlanet is undefined." ) ;
230
+ return ;
231
+ }
232
+
233
+ const existingItem = inventory . find ( item => item . name === resourceName ) ;
234
+
235
+ if ( existingItem ) {
236
+ // Update existing item in inventory
237
+ const { error } = await supabase
238
+ . from ( "inventory" )
239
+ . update ( { quantity : existingItem . amount + minedAmount } )
240
+ . eq ( "id" , existingItem . id )
241
+ . eq ( "owner" , session . user . id )
242
+ . eq ( "anomaly" , activePlanet . id ) ;
243
+
244
+ if ( error ) {
245
+ console . error ( "Error updating inventory:" , error ) ;
246
+ } else {
247
+ setInventory ( prev =>
248
+ prev . map ( item =>
249
+ item . id === existingItem . id
250
+ ? { ...item , amount : item . amount + minedAmount }
251
+ : item
252
+ )
253
+ ) ;
254
+ }
255
+ } else {
256
+ // Insert new item into inventory
257
+ const { data, error } = await supabase
258
+ . from ( "inventory" )
259
+ . insert ( [
260
+ {
261
+ item : resourceName , // Map this to an ID if needed
262
+ owner : session . user . id ,
263
+ quantity : minedAmount ,
264
+ anomaly : activePlanet . id ,
265
+ configuration : { Uses : 1 } ,
266
+ } ,
267
+ ] )
268
+ . select ( ) ;
269
+
270
+ if ( error ) {
271
+ console . error ( "Error inserting new item into inventory:" , error ) ;
272
+ } else {
273
+ setInventory ( prev => [
274
+ ...prev ,
275
+ { id : data [ 0 ] . id . toString ( ) , name : resourceName , amount : minedAmount } ,
276
+ ] ) ;
277
+ }
278
+ }
279
+ } ;
158
280
159
281
const toggleMap = ( ) => {
160
282
setActiveMap ( prev => prev === '2D' ? '3D' : '2D' )
161
283
}
162
284
285
+ const [ activeLandmark , setActiveLandmark ] = useState < Landmark | null > ( null ) ;
286
+
163
287
const handleLandmarkClick = ( id : string ) => {
164
- setLandmarks ( prev => prev . map ( landmark =>
165
- landmark . id === id ? { ...landmark , isOpen : ! landmark . isOpen } : landmark
166
- ) )
167
- }
288
+ console . log ( "Landmark clicked:" , id ) ;
289
+ const landmark = landmarks . find ( ( l ) => l . id === id ) ;
290
+ if ( landmark ) {
291
+ setActiveLandmark ( { ...landmark , isOpen : true } ) ;
292
+ }
293
+ } ;
294
+
295
+ const closeModal = ( ) => {
296
+ if ( activeLandmark ) {
297
+ setLandmarks ( ( prev : Landmark [ ] = [ ] ) =>
298
+ prev . map ( ( landmark : Landmark ) =>
299
+ landmark . id === activeLandmark . id
300
+ ? { ...landmark , isOpen : false }
301
+ : landmark
302
+ )
303
+ ) ;
304
+ setActiveLandmark ( null ) ;
305
+ }
306
+ } ;
168
307
169
308
return (
170
309
< div className = "relative h-screen w-full overflow-hidden bg-gray-100 text-[#2C4F64] flex flex-col" >
@@ -226,6 +365,38 @@ export function MiningComponentComponent() {
226
365
< div className = "bg-white bg-opacity-90 p-4 border-t border-gray-200" >
227
366
< Inventory />
228
367
</ div >
368
+ { activeLandmark && (
369
+ < LandmarkModal
370
+ landmark = { activeLandmark }
371
+ isOpen = { activeLandmark . isOpen }
372
+ onClose = { closeModal }
373
+ />
374
+ ) }
375
+ </ div >
376
+ ) ;
377
+ } ;
378
+
379
+ type LandmarkModalProps = {
380
+ landmark : Landmark | null ;
381
+ isOpen : boolean ;
382
+ onClose : ( ) => void ;
383
+ } ;
384
+
385
+ const LandmarkModal : React . FC < LandmarkModalProps > = ( { landmark, isOpen, onClose } ) => {
386
+ if ( ! isOpen || ! landmark ) return null ;
387
+
388
+ return (
389
+ < div className = "fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50" >
390
+ < div className = "bg-white rounded-lg shadow-lg max-w-md w-full p-6 relative" >
391
+ < button
392
+ className = "absolute top-3 right-3 text-gray-500 hover:text-gray-800"
393
+ onClick = { onClose }
394
+ >
395
+ ×
396
+ </ button >
397
+ < h2 className = "text-2xl font-bold mb-2" > { landmark . name } </ h2 >
398
+ < p className = "text-gray-700" > { landmark . description } </ p >
399
+ </ div >
229
400
</ div >
230
- )
231
- }
401
+ ) ;
402
+ } ;
0 commit comments