Improve looks of research menu
| 
		 After Width: | Height: | Size: 33 KiB  | 
| 
		 After Width: | Height: | Size: 25 KiB  | 
| 
		 After Width: | Height: | Size: 37 KiB  | 
| 
		 After Width: | Height: | Size: 28 KiB  | 
| 
		 After Width: | Height: | Size: 29 KiB  | 
| 
		 After Width: | Height: | Size: 34 KiB  | 
| 
		 After Width: | Height: | Size: 32 KiB  | 
| 
		 After Width: | Height: | Size: 37 KiB  | 
| 
						 | 
					@ -40,6 +40,11 @@ export const Buildings = async() => {
 | 
				
			||||||
    return db.collection('buildings');
 | 
					    return db.collection('buildings');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Research = async() => {
 | 
				
			||||||
 | 
					    const db = await getDB();
 | 
				
			||||||
 | 
					    return db.collection('research');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Lang = async (language = "en") => {
 | 
					export const Lang = async (language = "en") => {
 | 
				
			||||||
    const db = await getDB(`${config.MONGODB_DB}_${language}`);
 | 
					    const db = await getDB(`${config.MONGODB_DB}_${language}`);
 | 
				
			||||||
    return [
 | 
					    return [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					import DBResearch from '../../types/DBResearch';
 | 
				
			||||||
 | 
					import { Research } from '../db/mongodb';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getAllResearch = async () => {
 | 
				
			||||||
 | 
					    return (await Research()).find({}).toArray() as unknown as Array<DBResearch>;   
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getResearchById = async (id: string) => {
 | 
				
			||||||
 | 
					    return (await Research()).findOne({
 | 
				
			||||||
 | 
					        id
 | 
				
			||||||
 | 
					    }) as unknown as DBResearch;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,15 @@
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
import { Icon } from 'astro-icon/components'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import Layout from '../../layouts/Layout.astro';
 | 
					import Layout from '../../layouts/Layout.astro';
 | 
				
			||||||
import NavBar from '../../components/NavBar.astro';
 | 
					import NavBar from '../../components/NavBar.astro';
 | 
				
			||||||
import { getUserByAccessToken } from '../../lib/db/users';
 | 
					import { getUserByAccessToken } from '../../lib/db/users';
 | 
				
			||||||
import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
 | 
					import { getHighestWeightedLanguage, getLocales, getName, getObj } from '../../lib/utils/langDriver';
 | 
				
			||||||
import ResourceBar from '../../components/ResourceBar.astro';
 | 
					import ResourceBar from '../../components/ResourceBar.astro';
 | 
				
			||||||
 | 
					import ItemCard from '../../components/ItemCard.astro';
 | 
				
			||||||
 | 
					import DBResearch from '../../types/DBResearch';
 | 
				
			||||||
 | 
					import { getAllResearch } from '../../lib/db/research';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ResearchDetail = { id: string, level: number, requiredResearch: { id: string, level: number}[], cost: { [key: string]: number } };
 | 
					// const researchList = (await import('../../lib/data/research.json')).default;
 | 
				
			||||||
 | 
					const researchList = await getAllResearch();
 | 
				
			||||||
const researchList = (await import('../../lib/data/research.json')).default;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
 | 
					const loggedToken = Astro.cookies.get('sessionToken')?.value ?? null;
 | 
				
			||||||
const username = Astro.cookies.get('username')?.value ?? "";
 | 
					const username = Astro.cookies.get('username')?.value ?? "";
 | 
				
			||||||
| 
						 | 
					@ -22,57 +22,57 @@ const locale = await getHighestWeightedLanguage(Astro.request.headers.get('accep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const lang = await getLocales(locale);
 | 
					const lang = await getLocales(locale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const researchDetails: ResearchDetail[] = []; //TODO: Add union type for cost keys
 | 
					// type DBResearchDetails = DBResearch & { level: number };
 | 
				
			||||||
researchList.forEach(element => {
 | 
					// const researchDetails: DBResearchDetails[] = [];
 | 
				
			||||||
	const userLevel = checkUser.research.find(x => x.id === element.id)?.level ?? 0;
 | 
					// researchList.forEach(element => {
 | 
				
			||||||
	const tempResDetails: ResearchDetail = {
 | 
					// 	const userLevel = checkUser.research.find(x => x.id === element.id)?.level ?? 0;
 | 
				
			||||||
		id: element.id,
 | 
					// 	const tempResDetails: DBResearchDetails = {
 | 
				
			||||||
		level: userLevel,
 | 
					// 		level: userLevel,
 | 
				
			||||||
		requiredResearch: element.requirements.research,
 | 
					// 		...element
 | 
				
			||||||
		cost: {}
 | 
					// 	}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Object.entries(element.requirements.resources).forEach(([key, value]) => {
 | 
					// 	researchDetails.push(tempResDetails);
 | 
				
			||||||
		tempResDetails.cost[key] = value * Math.pow(element.multiplier, userLevel);
 | 
					// });
 | 
				
			||||||
	});
 | 
					
 | 
				
			||||||
	researchDetails.push(tempResDetails);
 | 
					
 | 
				
			||||||
});
 | 
					const modalSet: { [key: string]: { resources: Array<any>, research: Array<any>, buildings: Array<any> } } = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for(const research of researchList) {
 | 
				
			||||||
 | 
						modalSet[research.id] = {
 | 
				
			||||||
 | 
							resources: research.requirements.resources,
 | 
				
			||||||
 | 
							research: research.requirements.research,
 | 
				
			||||||
 | 
							buildings: research.requirements.buildings,
 | 
				
			||||||
 | 
							// energy: building.energy
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<Layout title="Research">
 | 
					<Layout title="Research">
 | 
				
			||||||
	<NavBar loggedIn="true" active="research" />
 | 
						<NavBar loggedIn="true" active="research" />
 | 
				
			||||||
	<ResourceBar />
 | 
						<ResourceBar />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {researchDetails.map(research => (
 | 
						<div id="research-modal-background">
 | 
				
			||||||
		<div class="research-card">
 | 
							<div id="research-modal-details" data-building-id="">
 | 
				
			||||||
			<h2>{getObj(lang, "research", research.id).name}</h2>
 | 
								<h3>Required resources</h3>
 | 
				
			||||||
			<div class="research-card-wrapper">
 | 
								<div class="research-modal-text" id="research-modal-req-resources">None</div>
 | 
				
			||||||
				<div class="research-image"></div>
 | 
								<h3>Required buildings</h3>
 | 
				
			||||||
				{getObj(lang, "research", research.id).description}<br />
 | 
								<div class="research-modal-text" id="research-modal-req-buildings">None</div>
 | 
				
			||||||
				
 | 
								<h3>Required research</h3>
 | 
				
			||||||
				<a id={`research_${research.id}`} href="#" class="a-button">{getName(lang, "general", "nav-research")}</a>
 | 
								<div class="research-modal-text" id="research-modal-req-research">None</div>
 | 
				
			||||||
				<div class="research-req-icon">
 | 
					 | 
				
			||||||
					<Icon class="research-req-icon-proper" name="mdi:help" />
 | 
					 | 
				
			||||||
					<div class="research-req-tooltip">
 | 
					 | 
				
			||||||
						<div>{getName(lang, "general", "required")}:</div>
 | 
					 | 
				
			||||||
						{research.requiredResearch.length !== 0 ? research.requiredResearch.map(req => (
 | 
					 | 
				
			||||||
							<div>
 | 
					 | 
				
			||||||
								{getObj(lang, "research", req.id).name} - {req.level}
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						)) : getName(lang, "general", "none")}
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
			<div>
 | 
					 | 
				
			||||||
				Level: {research.level}	
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
			<div class="research-cost-wrapper">
 | 
					 | 
				
			||||||
				{Object.entries(research.cost).map(([key, value]) => <div>
 | 
					 | 
				
			||||||
					{getName(lang, "resources", key)}: {value} ||
 | 
					 | 
				
			||||||
				</div>)}
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	))}
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<div class="research-cards">
 | 
				
			||||||
 | 
							{researchList.map(research => <>
 | 
				
			||||||
 | 
								<ItemCard
 | 
				
			||||||
 | 
									id={research.id}
 | 
				
			||||||
 | 
									name={getObj(lang, "research", research.id).name}
 | 
				
			||||||
 | 
									description={getObj(lang, "research", research.id).description ?? ""}
 | 
				
			||||||
 | 
									image={`/images/research/${research.id}.jpeg`}
 | 
				
			||||||
 | 
									button_type="general"
 | 
				
			||||||
 | 
									button_name="nav-research" />
 | 
				
			||||||
 | 
							</>)}
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
</Layout>
 | 
					</Layout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
| 
						 | 
					@ -154,53 +154,90 @@ researchList.forEach(element => {
 | 
				
			||||||
		color: lime;
 | 
							color: lime;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.research-card {
 | 
						.research-cards {
 | 
				
			||||||
		background: rgba(0, 0, 0, 0.5);
 | 
					 | 
				
			||||||
		padding: 1rem;
 | 
					 | 
				
			||||||
		margin: 1rem;
 | 
					 | 
				
			||||||
		border-radius: 8px;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.research-card-wrapper {
 | 
					 | 
				
			||||||
		display: flex;
 | 
							display: flex;
 | 
				
			||||||
 | 
							flex-direction: row;
 | 
				
			||||||
 | 
							flex-wrap: wrap;
 | 
				
			||||||
 | 
							row-gap: 40px;
 | 
				
			||||||
 | 
							column-gap: 2%;
 | 
				
			||||||
 | 
							margin-top: 40px;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.research-image {
 | 
						#research-modal-background {
 | 
				
			||||||
		background-color: pink;
 | 
							display: none;
 | 
				
			||||||
		border-radius: 20px;
 | 
							position: fixed;
 | 
				
			||||||
		width: 10em;
 | 
							top: 0;
 | 
				
			||||||
		height: 10em;
 | 
							left: 0;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.research-cost-wrapper {
 | 
					 | 
				
			||||||
		display: flex;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.research-req-icon {
 | 
					 | 
				
			||||||
		background-color: gray;
 | 
					 | 
				
			||||||
		width: 2em;
 | 
					 | 
				
			||||||
		height: 2em;
 | 
					 | 
				
			||||||
		font-size: 1em;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.research-req-icon-proper {
 | 
					 | 
				
			||||||
		width: 100%;
 | 
							width: 100%;
 | 
				
			||||||
		height: 100%;
 | 
							height: 100%;
 | 
				
			||||||
 | 
							background: rgba(0, 0, 0, 0.5);
 | 
				
			||||||
 | 
							z-index: 100;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.research-req-icon .research-req-tooltip {
 | 
						#research-modal-details {
 | 
				
			||||||
		position: absolute;
 | 
							display: none;
 | 
				
			||||||
		background-color: grey;
 | 
							position: fixed;
 | 
				
			||||||
		border-radius: 5px;
 | 
							top: 50%;
 | 
				
			||||||
		transition: opacity 1s;
 | 
							left: 50%;
 | 
				
			||||||
		opacity: 0;
 | 
							transform: translate(-50%, -50%);
 | 
				
			||||||
	}
 | 
							width: 80%;
 | 
				
			||||||
 | 
							max-width: 800px;
 | 
				
			||||||
	.research-req-icon:hover .research-req-tooltip {
 | 
							background: rgba(0, 0, 0, 0.9);
 | 
				
			||||||
		opacity: 1;
 | 
							border-radius: 8px;
 | 
				
			||||||
 | 
							padding: 1rem;
 | 
				
			||||||
 | 
							z-index: 101;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<script>
 | 
					<script define:vars={{ modalSet, lang }}>
 | 
				
			||||||
 | 
						const modalResources = document.getElementById("research-modal-req-resources");
 | 
				
			||||||
 | 
						const modalBuildings = document.getElementById("research-modal-req-buildings");
 | 
				
			||||||
 | 
						const modalResearch = document.getElementById("research-modal-req-research");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						document.querySelectorAll('.item-card-info-button').forEach((el) => {
 | 
				
			||||||
 | 
					        el.addEventListener('click', () => {
 | 
				
			||||||
 | 
					            // modal
 | 
				
			||||||
 | 
					            const modalDiv = document.getElementById('research-modal-details');
 | 
				
			||||||
 | 
					            if(!modalDiv) return;
 | 
				
			||||||
 | 
					            modalDiv.style.display = 'block';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								console.log(modalSet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								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('research-modal-background');
 | 
				
			||||||
 | 
					            if(!backgroundDiv) return;
 | 
				
			||||||
 | 
					            backgroundDiv.style.display = 'block';
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // close modal on background click
 | 
				
			||||||
 | 
					    const bg = document.getElementById('research-modal-background');
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    bg?.addEventListener('click', () => {
 | 
				
			||||||
 | 
					        const modalDiv = document.getElementById('research-modal-details');
 | 
				
			||||||
 | 
					        if(!modalDiv) return;
 | 
				
			||||||
 | 
					        modalDiv.style.display = 'none';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const backgroundDiv = document.getElementById('research-modal-background');
 | 
				
			||||||
 | 
					        if(!backgroundDiv) return;
 | 
				
			||||||
 | 
					        backgroundDiv.style.display = 'none';
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const allButtons = document.getElementsByClassName("a-button");
 | 
						const allButtons = document.getElementsByClassName("a-button");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for(const researchButton of allButtons) {
 | 
						for(const researchButton of allButtons) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					export default interface DBResearch {
 | 
				
			||||||
 | 
					    id: string,
 | 
				
			||||||
 | 
					    requirements: {
 | 
				
			||||||
 | 
					        buildings: Array<{ id: string, level: number }>,
 | 
				
			||||||
 | 
					        research: Array<{ id: string, level: number }>,
 | 
				
			||||||
 | 
					        resources: Array<{ name: string, amount: number }>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    time: number,
 | 
				
			||||||
 | 
					    multiplier: number,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||