Add simple mail system

This commit is contained in:
Aelita4 2024-11-22 15:26:28 +01:00
parent 42f9c75b06
commit 69b32f43b5
Signed by: Aelita4
GPG Key ID: E44490C2025906C1
8 changed files with 143 additions and 2 deletions

6
public/mail-notif.svg Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 4L3 9.31372L10.5 13.5M20 4L14.5 21L10.5 13.5M20 4L10.5 13.5" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="7" cy="7" r="4" fill="red" />
<circle cx="7" cy="7" r="1.5" fill="white" />
</svg>

After

Width:  |  Height:  |  Size: 472 B

4
public/mail.svg Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 4L3 9.31372L10.5 13.5M20 4L14.5 21L10.5 13.5M20 4L10.5 13.5" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 387 B

View File

@ -1,4 +1,6 @@
---
import { ObjectId } from 'mongodb';
import { checkForUnreadMails } from '../lib/db/mails';
import { getHighestWeightedLanguage, getLocales, getName } from '../lib/utils/langDriver';
interface Props {
@ -133,6 +135,9 @@ const topRow = filteredList.filter(element => element.position === "top");
const bottomRow = filteredList.filter(element => element.position === "bottom");
const username = Astro.cookies.get('username')?.value ?? "";
const userId = Astro.cookies.get('userid')?.value ?? 0;
const hasUnreadMail = await checkForUnreadMails(new ObjectId(userId));
---
<nav>
<div class="row">
@ -149,6 +154,7 @@ const username = Astro.cookies.get('username')?.value ?? "";
)}
<li class="nav-item"><span class="nav-username nav-keep-right">{username}</span></li>
{loggedIn === "true" ? <li class="nav-item"><img src="/gargamel.png" class="avatar-icon" /></li> : ""}
{loggedIn === "true" ? <li class="nav-item"><a href="/game/mail"><img src={`/mail${hasUnreadMail ? "-notif" : ""}.svg?${new Date().getTime()}`} class="mail-icon" /></a></li> : ""}
</ul>
</div>
<div class="row">
@ -204,7 +210,7 @@ nav ul {
.nav-keep-right {
position: absolute;
right: 80px;
right: 140px;
}
.active {
@ -216,6 +222,14 @@ nav ul {
border-radius: 50%;
border: 1px solid white;
position: absolute;
right: 73px;
}
.mail-icon {
height: 50px;
border-radius: 50%;
/* border: 1px solid white; */
position: absolute;
right: 13px;
}
</style>

View File

@ -4,6 +4,7 @@ import DBFleet from "../../../types/db/DBFleet";
import { updateFleet } from "../../db/fleet";
import { Planet } from "./PlanetManager";
import SystemManager, { System } from "./SystemManager";
import { sendMail } from "../../db/mails";
export type Fleet = {
id: ObjectId,
@ -77,6 +78,15 @@ export default class FleetManager {
await this.data.source.resources.updateAmount(this.data.cargo);
await this.data.source.ships.sync();
await this.data.source.resources.sync();
await sendMail(
null,
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
this.data.arrivalTime,
"Fleet Returned",
`Your fleet from ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`} has returned.\n
Ships: ${this.data.ships.map(ship => `${ship.amount} ${ship.id}`).join(', ')}\n
Cargo: ${this.data.cargo.length > 0 ? this.data.cargo.map(cargo => `${cargo.amount} ${cargo.id}`).join(', ') : 'None'}`
);
return true;
} else {
switch(this.data.mission) {
@ -85,17 +95,38 @@ export default class FleetManager {
case 'TRANSPORT':
await this.data.destination.resources.updateAmount(this.data.cargo);
await this.data.destination.resources.sync();
const cargo = JSON.parse(JSON.stringify(this.data.cargo)) as Array<{ id: string, amount: number }>;
this.data.cargo = [];
const arrived = new Date(this.data.arrivalTime);
await this.initiateReturn();
await sendMail(
null,
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
arrived,
"Fleet Arrived",
`Your fleet has arrived at ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`}.\n
Ships: ${this.data.ships.map(ship => `${ship.amount} ${ship.id}`).join(', ')}\n
Cargo delivered: ${cargo.length > 0 ? cargo.map(cargo => `${cargo.amount} ${cargo.id}`).join(', ') : 'None'}\n
Fleet will return at ${this.data.arrivalTime}`
);
return false;
case 'TRANSFER':
await this.data.destination.resources.updateAmount(this.data.cargo);
await this.data.destination.resources.sync();
this.data.cargo = [];
for(const ship of this.data.ships) {
this.data.destination.ships.addShips(ship.id, ship.amount);
}
await this.data.destination.ships.sync();
await sendMail(
null,
this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id,
this.data.arrivalTime,
"Fleet Arrived",
`Your fleet has arrived at ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`}.\n
Ships: ${this.data.ships.map(ship => `${ship.amount} ${ship.id}`).join(', ')}\n
Cargo delivered: ${this.data.cargo.length > 0 ? this.data.cargo.map(cargo => `${cargo.amount} ${cargo.id}`).join(', ') : 'None'}\n
Ships will stay at the destination.`
);
return true;
}
}

33
src/lib/db/mails.ts Normal file
View File

@ -0,0 +1,33 @@
import { ObjectId } from "mongodb";
import { Mails } from "./mongodb"
import DBMail from "../../types/db/DBMail";
export const getMailById = async (id: ObjectId) => {
return await (await Mails()).findOne({
_id: id
}) as DBMail;
}
export const getMailsByTo = async (to: ObjectId) => {
return await (await Mails()).find({
to
}).toArray() as DBMail[];
}
export const checkForUnreadMails = async (to: ObjectId) => {
return (await (await Mails()).find({
to,
read: false
}).toArray()).length > 0;
}
export const sendMail = async (from: ObjectId | null, to: ObjectId, date: Date, subject: string, body: string) => {
await (await Mails()).insertOne({
from,
to,
date,
subject,
body,
read: false
});
}

View File

@ -92,3 +92,8 @@ export const Lang = async (language = "en") => {
await db.collection('structures')
]
}
export const Mails = async() => {
const db = await getDB();
return db.collection('mails');
}

37
src/pages/game/mail.astro Normal file
View File

@ -0,0 +1,37 @@
---
import LoggedIn from '../../layouts/LoggedIn.astro';
import locationManager from '../../lib/classes/managers/LocationManager';
import { Planet } from '../../lib/classes/managers/PlanetManager';
import SystemManager from '../../lib/classes/managers/SystemManager';
import { getMailsByTo } from '../../lib/db/mails';
const { user, token, lang } = Astro.locals;
const active: SystemManager | Planet = Astro.locals.active;
const mails = (await getMailsByTo(user.id)).sort((a, b) => b.date.getTime() - a.date.getTime());
---
<LoggedIn id="mail" title="Mail">
{mails.map(mail => <div class="mail-card">
<h1>{!mail.read && "(NEW) "}{mail.subject} | from: {mail.from === null ? "SYSTEM" : locationManager.getUser(mail.from)?.username ?? "Unknown"}</h1>
<p>{mail.date.toLocaleString()}</p>
<hr />
<p style="white-space: pre-line">{mail.body}</p>
</div>)}
</LoggedIn>
<style>
.mail-card {
background: #333;
padding: 1em;
margin: 1em;
border-radius: 0.5em;
}
.mail-card h1 {
color: #fff;
font-size: 1.5em;
}
.mail-card p {
color: #fff;
}
</style>

11
src/types/db/DBMail.ts Normal file
View File

@ -0,0 +1,11 @@
import { ObjectId } from "mongodb";
export default interface DBMail {
_id: ObjectId;
from: ObjectId | null;
to: ObjectId;
date: Date;
subject: string;
body: string;
read: boolean;
}