diff --git a/app/scenes/mining/page.tsx b/app/scenes/mining/page.tsx index 040b4616..02e37f14 100644 --- a/app/scenes/mining/page.tsx +++ b/app/scenes/mining/page.tsx @@ -5,10 +5,10 @@ import { useActivePlanet } from "@/context/ActivePlanet"; import MineralDeposits from "@/components/Structures/Mining/Archive/AvailableDeposits"; import { SelectMineralPanel } from "@/components/Structures/Mining/Archive/MiningPanels"; import MineralsInventoryGrid from "@/components/Inventory/mineralsPanel"; -import { MiningComponentComponent } from "@/components/Structures/Mining/Mining"; -import { Card } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; +import { MiningComponent } from "@/components/Structures/Mining/Mining"; import StarnetLayout from "@/components/Layout/Starnet"; +import { EarthActionSceneLayout, EarthViewLayout } from "@/components/(scenes)/planetScene/layout"; +import StructureMissionGuide from "@/components/Layout/Guide"; enum Step { MineralDeposits = "MINERAL_DEPOSITS", @@ -17,14 +17,10 @@ enum Step { export default function Mining() { return ( - -
-
- -
- -
-
+ + + + ); }; diff --git a/components/(scenes)/planetScene/layout.tsx b/components/(scenes)/planetScene/layout.tsx index bce223bb..155a77b3 100644 --- a/components/(scenes)/planetScene/layout.tsx +++ b/components/(scenes)/planetScene/layout.tsx @@ -17,8 +17,8 @@ interface PlanetViewLayoutProps { children: React.ReactNode[]; }; -interface PlanetViewLayoutProps { - children: React.ReactNode[]; +interface PlanetActionSceneProps { + children: React.ReactNode; }; const PlanetViewLayout: React.FC = ({ children }) => { @@ -170,7 +170,7 @@ export const EarthViewLayout: React.FC = ({ />
- + {/* */}
{children.slice(0, 2).map((child, index) => ( @@ -202,4 +202,19 @@ export const EarthViewLayout: React.FC = ({
); +}; + +export const EarthActionSceneLayout: React.FC = ({ + children, +}) => { + return ( +
+ Earth Background + {children} +
+ ); }; \ No newline at end of file diff --git a/components/Layout/BottomMenu.tsx b/components/Layout/BottomMenu.tsx index 8210ccb0..70949701 100644 --- a/components/Layout/BottomMenu.tsx +++ b/components/Layout/BottomMenu.tsx @@ -1,11 +1,11 @@ -import { Globe, Rss, HelpCircle, Star } from "lucide-react"; +import { Globe, HelpCircle, Star, Pickaxe } from "lucide-react"; import { usePathname } from "next/navigation"; import Link from "next/link"; import { useState } from "react"; const menuItems = [ { icon: Globe, label: "Planet", href: "/" }, - { icon: Rss, label: "Mining", href: "/scenes/mining" }, + { icon: Pickaxe, label: "Mining", href: "/scenes/mining" }, { icon: Star, label: "Travel", href: "/scenes/travel" }, { icon: HelpCircle, diff --git a/components/Layout/Guide.tsx b/components/Layout/Guide.tsx index 6bfd228e..57bd4e95 100644 --- a/components/Layout/Guide.tsx +++ b/components/Layout/Guide.tsx @@ -2,9 +2,10 @@ import React, { useEffect, useState } from "react"; import { Button } from "../ui/button"; import { Card, CardContent } from "../ui/card"; import { motion, AnimatePresence } from "framer-motion"; -import { ChevronLeft, ChevronRight, CloudHail, HelpCircle, LightbulbIcon, Telescope, TreeDeciduous } from "lucide-react"; +import { ChevronLeft, ChevronRight, CloudHail, HelpCircle, LightbulbIcon, LucideTestTubeDiagonal, Pickaxe, Telescope, TestTube2, TreeDeciduous } from "lucide-react"; import { useSession, useSupabaseClient } from "@supabase/auth-helpers-react"; import MissionPathway from "../Missions/Pathway"; +import { useActivePlanet } from "@/context/ActivePlanet"; interface Mission { id: number; @@ -12,6 +13,7 @@ interface Mission { description: string; icon: React.ElementType; color: string; + requiredItem?: number; }; interface DialogueStep { @@ -26,6 +28,7 @@ const astronomyMissions: Mission[] = [ description: "Click on the 'Telescope' structure to make some classifications", icon: Telescope, color: 'text-cyan-300', + requiredItem: 3103, }, { id: 10000001, @@ -43,6 +46,7 @@ const biologistMissions: Mission[] = [ description: "Click on the 'Biodome' structure to make some classifications", icon: TreeDeciduous, color: 'text-green-300', + requiredItem: 3104, }, ]; @@ -53,23 +57,53 @@ const meteorologyMissions: Mission[] = [ description: "Click on your LIDAR module to make some classifications", icon: CloudHail, color: 'text-blue-300', + requiredItem: 3105, + }, +]; + +const globalMissions: Mission[] = [ + { + id: 200000015, + name: "Research a new module", + description: 'Click on your structure and then the "Research" tab to unlock new projects and data sources to contribute to!', + icon: TestTube2, + color: 'text-purple-300', + }, + { + id: 200000013, + name: "Collect some fuel", + description: "Click on the mining tab to visit some mineral deposits your probes have found and mine them for fuel", + icon: Pickaxe, + color: 'text-red-300', + }, + { + id: 30000001, + name: "Discover a new planet", + description: "Create and use a telescope to discover a new planet using the Planet Hunters module", + icon: Telescope, + color: 'text-purple-300', }, ]; // Research station - walk the user through this. Then upload data, verify/vet (consensus), then we introduce travel. Add a "close"/swipe-down option so that the tutorial section can be hidden/minimised. Then we go through the guide for the different views....and determine the differentials from Pathway.tsx and this new list // As well as researching for other projects/mission modules that aren't in `mission-selector` +// We'll also need to update this for different planets & chapters const dialogueSteps: DialogueStep[] = [ ]; -export default function StructureMissionGuide() { +const StructureMissionGuide = () => { const supabase = useSupabaseClient(); const session = useSession(); + const { activePlanet } = useActivePlanet(); + const [completedMissions, setCompletedMissions] = useState([]); const [loading, setLoading] = useState(true); const [currentCategory, setCurrentCategory] = useState(0); - const [minimized, setMinimized] = useState(false); // State to handle minimization + const [minimized, setMinimized] = useState(false); + const [ownedItems, setOwnedItems] = useState([]); + const [scrollableMissions, setScrollableMissions] = useState([]); const categories = [ { missions: astronomyMissions, name: 'Astronomer' }, @@ -78,43 +112,67 @@ export default function StructureMissionGuide() { ]; useEffect(() => { - async function fetchCompletedMissions() { - if (!session?.user?.id) return; - - const { data, error } = await supabase - .from('missions') - .select('mission') - .eq('user', session.user.id); - - if (error) { - console.error("Error fetching completed missions:", error); - } else { - const completedMissionIds = data.map((mission: { mission: number }) => mission.mission); + async function fetchInventoryAndCompletedMissions() { + if (!session?.user?.id || !activePlanet?.id) return; + + try { + const { data: inventoryData, error: inventoryError } = await supabase + .from('inventory') + .select('item') + .eq('owner', session.user.id) + .eq('anomaly', activePlanet.id) + .in('item', [3103, 3104, 3105, 3106]); + + if (inventoryError) throw inventoryError; + + const ownedItems = inventoryData.map((inv: { item: number }) => inv.item); + setOwnedItems(ownedItems); + + const { data: missionData, error: missionError } = await supabase + .from('missions') + .select('mission') + .eq('user', session.user.id); + + if (missionError) throw missionError; + + const completedMissionIds = missionData.map((mission: { mission: number }) => mission.mission); setCompletedMissions(completedMissionIds); + + if (ownedItems.includes(3103)) { + setCurrentCategory(0); // Astronomy + } else if (ownedItems.includes(3104)) { + setCurrentCategory(1); // Biology + } else if (ownedItems.includes(3105)) { + setCurrentCategory(2); // Meteorology + } else { + setCurrentCategory(Math.floor(Math.random() * categories.length)); // Random category if no specific items are owned + } + } catch (error) { + console.error("Error fetching inventory or missions:", error); } setLoading(false); } - fetchCompletedMissions(); - }, [session, supabase]); - - const handleNextCategory = () => { - setCurrentCategory((prevCategory) => (prevCategory + 1) % categories.length); - }; - - const handlePreviousCategory = () => { - setCurrentCategory((prevCategory) => (prevCategory - 1 + categories.length) % categories.length); - }; + fetchInventoryAndCompletedMissions(); + }, [session, activePlanet, supabase]); - const toggleMinimize = () => { - setMinimized(!minimized); + useEffect(() => { + const missionsToDisplay = [ + ...categories[currentCategory].missions.slice(0, 2), // Get only the first 2 missions + ...globalMissions.slice(0, 2), // Add 2 global missions + ]; + setScrollableMissions(missionsToDisplay); + }, [currentCategory]); + + const userHasRequiredItem = (requiredItem?: number) => { + return requiredItem ? ownedItems.includes(requiredItem) : false; }; return (
{minimized ? ( - @@ -122,13 +180,11 @@ export default function StructureMissionGuide() {
- {/* Mission Group Header */}

- Mission guide for {categories[currentCategory].name} pathway + Mission Guide for {categories[currentCategory].name} Pathway

-
-
- {loading ? ( -

Loading missions...

- ) : ( - categories[currentCategory].missions.map((mission) => ( - - - -
-

{mission.name}

- {completedMissions.includes(mission.id) ? ( -

- {mission.description} -

- ) : ( -

{mission.description}

- )} -
-
-
- )) - )} +
+

+ Welcome! Build structures like the Telescope to complete missions and expand your research. + Click the 'Guide' button to view your missions. +

+
+ + {/* Scrollable Missions Section */} +
+
+ {scrollableMissions.map((mission) => ( +
+ + + +
+

+ {mission.name} +

+

{mission.description}

+ {userHasRequiredItem(mission.requiredItem) && ( + Ready to complete! + )} +
+
+
+
+ ))} +
)}
); -}; \ No newline at end of file +}; + +export default StructureMissionGuide; \ No newline at end of file diff --git a/components/Structures/Auto/AllAutomatons.tsx b/components/Structures/Auto/AllAutomatons.tsx index eefda29c..da3c626d 100644 --- a/components/Structures/Auto/AllAutomatons.tsx +++ b/components/Structures/Auto/AllAutomatons.tsx @@ -3,7 +3,7 @@ import React, { useState, useEffect } from "react"; import { useSession, useSupabaseClient } from "@supabase/auth-helpers-react"; import { useActivePlanet } from "@/context/ActivePlanet"; -import { MiningComponentComponent } from "../Mining/Mining"; +import { MiningComponent } from "../Mining/Mining"; interface InventoryItem { id: number; @@ -116,7 +116,7 @@ export default function AllAutomatonsOnActivePlanet() { × - +
)} diff --git a/components/Structures/Mining/ControlPanel.tsx b/components/Structures/Mining/ControlPanel.tsx index 88c923ad..4fc6e4d5 100644 --- a/components/Structures/Mining/ControlPanel.tsx +++ b/components/Structures/Mining/ControlPanel.tsx @@ -5,37 +5,51 @@ import { useSession, useSupabaseClient } from '@supabase/auth-helpers-react' import { useActivePlanet } from '@/context/ActivePlanet' import LaunchpadStatus from '../Launchpad/LaunchpadStatus' +type MineralDeposit = { + id: string; + name: string; + quantity: number; +}; + type Rover = { - id: string - name: string - speed: number - efficiency: number - miningLevel: number -} + id: string; + name: string; + speed: number; + efficiency: number; + miningLevel: number; +}; type Props = { - rovers: Rover[] - selectedRover: Rover | null - onRoverSelect: (rover: Rover) => void - onStartMining: () => void - isMining: boolean -} + rovers: Rover[]; + selectedRover: Rover | null; + onRoverSelect: (rover: Rover) => void; + onStartMining: () => void; + isMining: boolean; + selectedDeposit: MineralDeposit | null; +}; -export function ControlPanel({ rovers = [], selectedRover, onRoverSelect, onStartMining, isMining }: Props) { - const [speed, setSpeed] = useState(10) - const [efficiency, setEfficiency] = useState(0.8) - const [miningLevel, setMiningLevel] = useState(1) +export function ControlPanel({ + rovers = [], + selectedRover, + onRoverSelect, + onStartMining, + isMining, + selectedDeposit, +}: Props) { + const [speed, setSpeed] = useState(10); + const [efficiency, setEfficiency] = useState(0.8); + const [miningLevel, setMiningLevel] = useState(1); useEffect(() => { if (selectedRover) { - setSpeed(selectedRover.speed) - setEfficiency(selectedRover.efficiency) - setMiningLevel(selectedRover.miningLevel) + setSpeed(selectedRover.speed); + setEfficiency(selectedRover.efficiency); + setMiningLevel(selectedRover.miningLevel); } - }, [selectedRover]) + }, [selectedRover]); const handleRoverSelect = (rover: Rover) => { - onRoverSelect(rover) + onRoverSelect(rover); }; return ( @@ -46,9 +60,13 @@ export function ControlPanel({ rovers = [], selectedRover, onRoverSelect, onStar

Select Rover

{rovers.map(rover => ( -
handleRoverSelect(rover)} >
@@ -59,68 +77,32 @@ export function ControlPanel({ rovers = [], selectedRover, onRoverSelect, onStar ))}
- - {selectedRover && ( -
-

Customize Rover

-
- - setSpeed(Number(e.target.value))} - className="my-2 w-full" - /> - {speed} -
-
- - setEfficiency(Number(e.target.value) / 100)} - className="my-2 w-full" - /> - {(efficiency * 100).toFixed(0)}% -
-
- - setMiningLevel(Number(e.target.value))} - className="my-2 w-full" - /> - {miningLevel} -
+ + {/* Now you can use selectedDeposit */} + {selectedDeposit && ( +
+

Selected Deposit

+

+ Name: {selectedDeposit.name}, Quantity: {selectedDeposit.quantity} +

)} - -
); -}; - - - -// test +} function AddMineralDeposits() { const supabase = useSupabaseClient(); diff --git a/components/Structures/Mining/Deposits.tsx b/components/Structures/Mining/Deposits.tsx index d1689215..10ea8745 100644 --- a/components/Structures/Mining/Deposits.tsx +++ b/components/Structures/Mining/Deposits.tsx @@ -4,15 +4,15 @@ import React from "react"; import { Diamond } from "lucide-react"; export type MineralDeposit = { - id: string; - mineral: string; - quantity: number; - availableAmount: number; - level: number; - uses: string[]; - position: { x: number; y: number }; - }; - + name: string; + id: string; + mineral: string; + quantity: number; + availableAmount: number; + level: number; + uses: string[]; + position: { x: number; y: number }; +}; type Props = { deposits: MineralDeposit[]; onSelect: (deposit: MineralDeposit) => void; diff --git a/components/Structures/Mining/Mining.tsx b/components/Structures/Mining/Mining.tsx index 1a742659..44216d6d 100644 --- a/components/Structures/Mining/Mining.tsx +++ b/components/Structures/Mining/Mining.tsx @@ -10,6 +10,7 @@ import { useActivePlanet } from '@/context/ActivePlanet' import { Info } from 'lucide-react' export type MineralDeposit = { + name: string; id: string; mineral: string; quantity: number; @@ -27,7 +28,7 @@ type Rover = { miningLevel: number }; -export function MiningComponentComponent() { +export function MiningComponent() { const supabase = useSupabaseClient() const session = useSession() const { activePlanet } = useActivePlanet() @@ -63,13 +64,14 @@ export function MiningComponentComponent() { const formattedDeposits = data?.map((deposit) => ({ id: deposit.id, + name: deposit.mineralconfiguration.mineral || "Unknown", mineral: deposit.mineralconfiguration.mineral || "Unknown", quantity: deposit.mineralconfiguration.quantity || 0, availableAmount: deposit.mineralconfiguration.availableAmount || 0, level: deposit.mineralconfiguration.level || 1, uses: deposit.mineralconfiguration.uses || [], - position: deposit.mineralconfiguration.position || { x: 0, y: 0 }, - })) + position: deposit.mineralconfiguration.position || { x: 50, y: 50 }, + })); setMineralDeposits(formattedDeposits || []) } @@ -136,7 +138,6 @@ export function MiningComponentComponent() { setRoverPosition({ x: 50, y: 50 }); setIsMining(false); - // Mining logic: Insert or update inventory const { mineral, quantity } = selectedDeposit; try { @@ -168,7 +169,6 @@ export function MiningComponentComponent() { } if (existingItem) { - // Update the existing item quantity const newQuantity = existingItem.quantity + quantity; const { error: updateError } = await supabase .from('inventory') @@ -181,7 +181,6 @@ export function MiningComponentComponent() { console.log(`Updated inventory item. New quantity: ${newQuantity}`); } } else { - // Insert a new inventory item const { error: insertError } = await supabase .from('inventory') .insert({ @@ -201,7 +200,7 @@ export function MiningComponentComponent() { } catch (error) { console.error('Error during mining process:', error); } - }, 5000); // Simulate mining completion delay + }, 5000); } }; @@ -209,32 +208,30 @@ export function MiningComponentComponent() { }; }; - return ( -
-
-
- -
-
+ return ( // w-[95%] +
+
+ +
+ +
+

Inventory - {/* */} - - {/* */} +

+
-
+

Mineral Deposits - {/* */} - - {/* */} +

-
+ +

- Control Panel - {/* */} - - {/* */} + Rovers +

-
- ); + ); }; \ No newline at end of file diff --git a/components/Structures/Mining/TopographicMap.tsx b/components/Structures/Mining/TopographicMap.tsx index 6672a7db..0170e189 100644 --- a/components/Structures/Mining/TopographicMap.tsx +++ b/components/Structures/Mining/TopographicMap.tsx @@ -16,7 +16,7 @@ type Props = { selectedDeposit: MineralDeposit | null; }; -export function TopographicMap({ deposits = [], roverPosition, selectedDeposit }: Props) { +export function TopographicMap({ deposits = [], roverPosition, selectedDeposit }: Props) { const canvasRef = useRef(null); useEffect(() => { @@ -75,7 +75,7 @@ export function TopographicMap({ deposits = [], roverPosition, selectedDeposit } }, [deposits]); return ( -
+
{roverPosition && ( ([]) - const [currentStep, setCurrentStep] = useState(0) - - const handleCompleteMission = (missionId: string) => { - if (!completedMissions.includes(missionId)) { - setCompletedMissions([...completedMissions, missionId]) - } - } - - const handleNext = () => { - setCurrentStep((prevStep) => Math.min(prevStep + 1, dialogueSteps.length - 1)) - } - - const handlePrevious = () => { - setCurrentStep((prevStep) => Math.max(prevStep - 1, 0)) - } - - const currentDialogue = dialogueSteps[currentStep] - const isDialogueAvailable = currentDialogue.requiredMissions.every(mission => completedMissions.includes(mission)) - - return ( -
- - -
-
-

- Galactic Mission Guide -

- - - {isDialogueAvailable ? ( -

{currentDialogue.text}

- ) : ( -

Complete more missions to unlock this guidance.

- )} -
-
-
-
- -
- Step {currentStep + 1} of {dialogueSteps.length} -
- -
-
-
-
- {missions.map((mission) => ( - handleCompleteMission(mission.id)} - > - - -
-

{mission.name}

-

{mission.description}

-
- {completedMissions.includes(mission.id) && ( -
- )} -
-
- ))} -
-
-
- - {/* Sci-fi background elements */} -
-
-
-
-
-
-
-
-
- ) -} \ No newline at end of file