AstroCol/src/pages/game/buildings.astro

274 lines
8.0 KiB
Plaintext

---
import Layout from '../../layouts/Layout.astro';
import NavBar from '../../components/NavBar.astro';
import BuildingCard from '../../components/ItemCard.astro';
import { getUserByAccessToken } from '../../lib/db/users';
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
import ResourceBar from '../../components/ResourceBar.astro';
import { getAllBuildings } from '../../lib/db/buildings';
import locationManager from '../../lib/classes/managers/LocationManager';
import { ObjectId } from 'mongodb';
import DBBuilding from '../../types/db/DBBuilding';
const buildingsList = await getAllBuildings();
const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
const username = Astro.cookies.get('username')?.value ?? "";
if(loggedToken === null || username === "") return Astro.redirect('/logout');
const checkUser = await getUserByAccessToken(loggedToken);
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
const locale = Astro.cookies.get('language')?.value ?? await getHighestWeightedLanguage(Astro.request.headers.get('accept-language'));
const lang = await getLocales(locale);
const planetId = Astro.cookies.get('planetid')?.value ?? "";
if(planetId === "") return "No planet selected";
const planet = locationManager.getPlanet(new ObjectId(planetId));
if(!planet) return "Planet not found";
const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any>, energy: number } } = {};
for(const building of buildingsList) {
modalSet[building.id] = {
resources: building.requirements.resources.map(resource => {
return {
id: resource.id,
amount: Math.pow(building.multiplier, (planet.buildings.getBuildingById(building.id)?.level ?? 0) ) * resource.amount
};
}),
research: building.requirements.research,
buildings: building.requirements.buildings,
energy: building.energy
};
}
const buildingsByCategory = buildingsList.reduce((acc: { [key: string]: Array<DBBuilding & { level: number }> }, building) => {
if(!acc[building.category]) acc[building.category] = [];
acc[building.category].push({ ...building, level: planet.buildings.getBuildingById(building.id)?.level ?? 0 });
return acc;
}, {});
---
<Layout title="Buildings">
<NavBar loggedIn="true" active="buildings" />
<ResourceBar />
<div id="building-modal-background">
<div id="building-modal-details" data-building-id="">
<h3>Required resources</h3>
<div class="building-modal-text" id="building-modal-req-resources">None</div>
<h3>Required buildings</h3>
<div class="building-modal-text" id="building-modal-req-buildings">None</div>
<h3>Required research</h3>
<div class="building-modal-text" id="building-modal-req-research">None</div>
</div>
</div>
{Object.entries(buildingsByCategory).map(([category, buildings]) => <>
<h1>{getName(lang, 'buildings', `cat-${category}`)}</h1>
<div class="building-cat">
{buildings.map(building => (
<BuildingCard
id={building.id}
level={building.level.toString()}
name={getObj(lang, "buildings", building.id).name}
description={getObj(lang, "buildings", building.id).description ?? ""}
image={`/images/buildings/${building.id}.jpeg`}
button_type="general"
button_name="nav-build" />
))}
</div>
</>)}
</Layout>
<style>
* {
color: white;
}
main {
margin: auto;
padding: 1rem;
width: 800px;
max-width: calc(100% - 2rem);
color: white;
font-size: 20px;
line-height: 1.6;
}
.building-cat {
display: flex;
flex-direction: row;
flex-wrap: wrap;
row-gap: 40px;
column-gap: 2%;
}
#building-modal-background {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 100;
}
#building-modal-details {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
max-width: 800px;
background: rgba(0, 0, 0, 0.9);
border-radius: 8px;
padding: 1rem;
z-index: 101;
}
.astro-a {
position: absolute;
top: -32px;
left: 50%;
transform: translatex(-50%);
width: 220px;
height: auto;
z-index: -1;
}
h3 {
font-size: 2rem;
font-weight: 700;
line-height: 1;
text-align: center;
margin-bottom: 1em;
}
.building-modal-text {
font-size: 1.5rem;
}
.text-gradient {
background-image: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 400%;
background-position: 0%;
}
.instructions {
margin-bottom: 2rem;
border: 1px solid rgba(var(--accent-light), 25%);
background: linear-gradient(rgba(var(--accent-dark), 66%), rgba(var(--accent-dark), 33%));
padding: 1.5rem;
border-radius: 8px;
}
.instructions code {
font-size: 0.8em;
font-weight: bold;
background: rgba(var(--accent-light), 12%);
color: rgb(var(--accent-light));
border-radius: 4px;
padding: 0.3em 0.4em;
}
.instructions strong {
color: rgb(var(--accent-light));
}
.link-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
gap: 2rem;
padding: 0;
}
.a-button {
text-decoration: none;
color: green;
}
.a-button:hover {
color: lime;
}
</style>
<script define:vars={{ modalSet, lang, planetId }}>
const modalResources = document.getElementById("building-modal-req-resources");
const modalBuildings = document.getElementById("building-modal-req-buildings");
const modalResearch = document.getElementById("building-modal-req-research");
document.querySelectorAll('.item-card-info-button').forEach((el) => {
el.addEventListener('click', () => {
// modal
const modalDiv = document.getElementById('building-modal-details');
if(!modalDiv) return;
modalDiv.style.display = 'block';
const reqResources = modalSet[el.parentElement.parentElement.dataset.id]?.resources ?? [];
const reqBuildings = modalSet[el.parentElement.parentElement.dataset.id]?.buildings ?? [];
const reqResearch = modalSet[el.parentElement.parentElement.dataset.id]?.research ?? [];
modalResources.innerHTML = reqResources.length === 0 ? "None" : reqResources.map(resource => {
return `${lang['resources'].find(r => r.id === resource.id).name}: ${resource.amount}`;
}).join("<br />");
modalBuildings.innerHTML = reqBuildings.length === 0 ? "None" : reqBuildings.map(building => {
return `${lang['buildings'].find(b => b.id === building.id).name}: ${building.level}`;
}).join("<br />");
modalResearch.innerHTML = reqResearch.length === 0 ? "None" : reqResearch.map(research => {
return `${lang['research'].find(r => r.id === research.id).name}: ${research.level}`;
}).join("<br />");
// background
const backgroundDiv = document.getElementById('building-modal-background');
if(!backgroundDiv) return;
backgroundDiv.style.display = 'block';
});
});
// close modal on background click
const bg = document.getElementById('building-modal-background');
bg?.addEventListener('click', () => {
const modalDiv = document.getElementById('building-modal-details');
if(!modalDiv) return;
modalDiv.style.display = 'none';
const backgroundDiv = document.getElementById('building-modal-background');
if(!backgroundDiv) return;
backgroundDiv.style.display = 'none';
});
const allButtons = document.getElementsByClassName("item-card-build");
for(const buildingButton of allButtons) {
buildingButton.addEventListener("click", async () => {
const id = buildingButton.id.split("_")[1];
const response = await fetch('/api/build/createBuilding', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
building: id,
planet: planetId
})
});
if(response.status === 200) {
window.location.reload();
} else {
alert("Failed to build building: " + JSON.stringify(await response.json()));
}
});
}
</script>