Created styling standard

This commit is contained in:
Tim Howitz 2025-05-04 16:04:44 +01:00
parent 92fbd9369c
commit ec25bf0725
26 changed files with 551 additions and 505 deletions

62
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,62 @@
{
"editor.insertSpaces": true,
// Ignores the warning when Git is missing
"git.ignoreMissingGitWarning": true,
// Disable crash reports being sent to Microsoft.
"telemetry.enableCrashReporter": false,
// Disable usage data and errors being sent to Microsoft.
"telemetry.enableTelemetry": false,
"editor.formatOnSave": true,
"cmake.configureOnOpen": false,
"[python]": {
"editor.defaultFormatter": "ms-python.autopep8",
"editor.formatOnSave": true
},
"autopep8.args": ["--max-line-length=200"],
"editor.detectIndentation": false,
"git.confirmSync": false,
"editor.rulers": [
{
"column": 120
}
],
"git.autofetch": true,
"files.autoSave": "onFocusChange",
"cSpell.language": "en-GB",
"C_Cpp.formatting": "disabled",
"cmake.showOptionsMovedNotification": false,
"diffEditor.renderSideBySide": false,
"terminal.integrated.commandsToSkipShell": ["matlab.interrupt"],
"[matlab]": {
"editor.defaultFormatter": "AffenWiesel.matlab-formatter"
},
"workbench.editorAssociations": {
"*.pdf": "latex-workshop-pdf-hook"
},
"notebook.output.textLineLimit": 50,
"prettier.printWidth": 130,
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"prettier.useTabs": true,
"editor.tabSize": 4,
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[cpp]": {
"editor.defaultFormatter": "ms-vscode.cpptools"
},
"C_Cpp.default.cppStandard": "gnu++23",
"C_Cpp.default.cStandard": "gnu23",
"diffEditor.hideUnchangedRegions.enabled": true,
"python.createEnvironment.trigger": "off",
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"importSorter.generalConfiguration.sortOnBeforeSave": true,
"cSpell.words": [
"vars"
]
}

View File

@ -9,8 +9,9 @@ const compat = new FlatCompat({
baseDirectory: __dirname, baseDirectory: __dirname,
}); });
const eslintConfig = [ export default tseslint.config([...compat.extends("next/core-web-vitals", "next/typescript")], {
...compat.extends("next/core-web-vitals", "next/typescript"), rules: {
]; "no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
export default eslintConfig; },
});

View File

@ -1,6 +1,6 @@
import { NextResponse } from 'next/server'; import { NextResponse } from "next/server";
import { PrismaClient } from '@prisma/client'; import { PrismaClient } from "@prisma/client";
const usingPrisma = false; const usingPrisma = false;
let prisma: PrismaClient; let prisma: PrismaClient;

View File

@ -1,6 +1,6 @@
import path from "path";
import fs from "fs";
import csv from "csv-parser"; import csv from "csv-parser";
import fs from "fs";
import path from "path";
export type User = { export type User = {
name: string; name: string;

View File

@ -1,9 +1,9 @@
import bcrypt from 'bcrypt'; import bcrypt from "bcrypt";
import { NextResponse } from 'next/server'; import { NextResponse } from "next/server";
import { PrismaClient } from '@prisma/client'; import { PrismaClient } from "@prisma/client";
import { findUserByEmail, readUserCsv, User } from '../functions/csvReadWrite'; import { findUserByEmail, readUserCsv, User } from "../functions/csvReadWrite";
const usingPrisma = false; const usingPrisma = false;
let prisma: PrismaClient; let prisma: PrismaClient;

View File

@ -1,6 +1,6 @@
import { NextResponse } from 'next/server'; import { NextResponse } from "next/server";
import { PrismaClient } from '@prisma/client'; import { PrismaClient } from "@prisma/client";
const usingPrisma = false; const usingPrisma = false;
let prisma: PrismaClient; let prisma: PrismaClient;

View File

@ -1,11 +1,9 @@
import bcrypt from 'bcrypt'; import bcrypt from "bcrypt";
import { NextResponse } from 'next/server'; import { NextResponse } from "next/server";
import { PrismaClient } from '@prisma/client'; import { PrismaClient } from "@prisma/client";
import { import { findUserByEmail, passwordStrengthCheck, readUserCsv, User, writeUserCsv } from "../functions/csvReadWrite";
findUserByEmail, passwordStrengthCheck, readUserCsv, User, writeUserCsv
} from '../functions/csvReadWrite';
const usingPrisma = false; const usingPrisma = false;
let prisma: PrismaClient; let prisma: PrismaClient;

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import Image from 'next/image'; import Image from "next/image";
import React, { useState } from 'react'; import React, { useState } from "react";
const ContactUs = () => { const ContactUs = () => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({

View File

@ -1,11 +1,11 @@
"use client"; "use client";
import { useMemo, useState } from 'react'; import { useMemo, useState } from "react";
import useSWR from 'swr'; import useSWR from "swr";
import Map from '@components/Map'; import Map from "@components/Map";
import Sidebar from '@components/Sidebar'; import Sidebar from "@components/Sidebar";
import { fetcher } from '@utils/fetcher'; import { fetcher } from "@utils/fetcher";
export default function Earthquakes() { export default function Earthquakes() {
const [selectedEventId, setSelectedEventId] = useState(""); const [selectedEventId, setSelectedEventId] = useState("");

View File

@ -1,11 +1,11 @@
"use client"; "use client";
import { useMemo, useState } from 'react'; import { useMemo, useState } from "react";
import useSWR from 'swr'; import useSWR from "swr";
import Sidebar from '@/components/Sidebar'; import Sidebar from "@/components/Sidebar";
import Map from '@components/Map'; import Map from "@components/Map";
import { fetcher } from '@utils/fetcher'; import { fetcher } from "@utils/fetcher";
export default function Observatories() { export default function Observatories() {
const [selectedEventId, setSelectedEventId] = useState(""); const [selectedEventId, setSelectedEventId] = useState("");

View File

@ -11,61 +11,37 @@ const OurMission = () => {
{/* Content Area */} {/* Content Area */}
<div className="relative z-10 max-w-4xl mx-auto p-5 bg-white bg-opacity-90 shadow-lg rounded-lg"> <div className="relative z-10 max-w-4xl mx-auto p-5 bg-white bg-opacity-90 shadow-lg rounded-lg">
<h1 className="text-3xl font-bold text-center text-gray-800 mb-6"> <h1 className="text-3xl font-bold text-center text-gray-800 mb-6">Our Mission</h1>
Our Mission
</h1>
<p className="text-lg text-gray-600 leading-relaxed mb-4"> <p className="text-lg text-gray-600 leading-relaxed mb-4">
At{" "} At <span className="font-semibold text-blue-600">Earthquake Awareness Initiative</span>, our mission is to help people
<span className="font-semibold text-blue-600"> worldwide prepare for and recover from earthquakes. Through education, research, and innovative technology, we work
Earthquake Awareness Initiative tirelessly to empower communities with the knowledge they need to stay safe before, during, and after seismic events.
</span>
, our mission is to help people worldwide prepare for and recover
from earthquakes. Through education, research, and innovative
technology, we work tirelessly to empower communities with the
knowledge they need to stay safe before, during, and after seismic
events.
</p> </p>
<p className="text-lg text-gray-600 leading-relaxed mb-4"> <p className="text-lg text-gray-600 leading-relaxed mb-4">
We aim to bridge the gap between scientific research and community We aim to bridge the gap between scientific research and community awareness by providing resources, tools, and
awareness by providing resources, tools, and real-time updates for real-time updates for earthquake preparedness. Together, we aspire to save lives, mitigate impacts, and foster
earthquake preparedness. Together, we aspire to save lives, mitigate resilience against nature's powerful forces.
impacts, and foster resilience against nature's powerful forces.
</p> </p>
<div className="flex flex-col md:flex-row md:justify-evenly items-center mt-6"> <div className="flex flex-col md:flex-row md:justify-evenly items-center mt-6">
<div className="flex flex-col items-center p-10"> <div className="flex flex-col items-center p-10">
<img <img src="education.png" alt="Education Icon" className="h-20 w-20 mb-8" />
src="education.png"
alt="Education Icon"
className="h-20 w-20 mb-8"
/>
<h3 className="text-xl font-bold text-gray-700 mb-2">Education</h3> <h3 className="text-xl font-bold text-gray-700 mb-2">Education</h3>
<p className="text-sm text-gray-500 text-center"> <p className="text-sm text-gray-500 text-center">
Providing accessible resources to educate people about earthquake Providing accessible resources to educate people about earthquake preparedness.
preparedness.
</p> </p>
</div> </div>
<div className="flex flex-col items-center p-10"> <div className="flex flex-col items-center p-10">
<img <img src="research.jpg" alt="Research Icon" className="h-20 w-20 mb-4" />
src="research.jpg"
alt="Research Icon"
className="h-20 w-20 mb-4"
/>
<h3 className="text-xl font-bold text-gray-700 mb-2">Research</h3> <h3 className="text-xl font-bold text-gray-700 mb-2">Research</h3>
<p className="text-sm text-gray-500 text-center"> <p className="text-sm text-gray-500 text-center">
Supporting scientific studies to enhance understanding of seismic Supporting scientific studies to enhance understanding of seismic activity.
activity.
</p> </p>
</div> </div>
<div className="flex flex-col items-center p-10"> <div className="flex flex-col items-center p-10">
<img <img src="tech.jpg" alt="Technology Icon" className="h-20 w-20 mb-8" />
src="tech.jpg"
alt="Technology Icon"
className="h-20 w-20 mb-8"
/>
<h3 className="text-xl font-bold text-gray-700 mb-2">Technology</h3> <h3 className="text-xl font-bold text-gray-700 mb-2">Technology</h3>
<p className="text-sm text-gray-500 text-center"> <p className="text-sm text-gray-500 text-center">
Leveraging innovation to deliver real-time alerts and safety Leveraging innovation to deliver real-time alerts and safety tools.
tools.
</p> </p>
</div> </div>
</div> </div>

View File

@ -13,8 +13,6 @@ export default function Home() {
</div> </div>
</div> </div>
<div className="mx-auto mt-20 w-4/6 px-2 border border-black divide-y"> <div className="mx-auto mt-20 w-4/6 px-2 border border-black divide-y">
{["Earthquake 1", "Earthquake 2", "Earthquake 3"].map((name) => ( {["Earthquake 1", "Earthquake 2", "Earthquake 3"].map((name) => (
<div className="px-5 py-5" key={name}> <div className="px-5 py-5" key={name}>

View File

@ -1,11 +1,11 @@
"use client"; "use client";
import Image from 'next/image'; import Image from "next/image";
import { Dispatch, SetStateAction, useCallback, useState } from 'react'; import { Dispatch, SetStateAction, useCallback, useState } from "react";
import Artifact from '@appTypes/Artifact'; import Artifact from "@appTypes/Artifact";
import { Currency } from '@appTypes/StoreModel'; import { Currency } from "@appTypes/StoreModel";
import Sidebar from '@components/Sidebar'; import Sidebar from "@components/Sidebar";
import { useStoreState } from '@hooks/store'; import { useStoreState } from "@hooks/store";
// Artifacts Data // Artifacts Data
const artifacts: Artifact[] = [ const artifacts: Artifact[] = [

View File

@ -1,5 +1,5 @@
"use client"; // Required for components in Next.js (using client-side rendering) "use client"; // Required for components in Next.js (using client-side rendering)
import Image from 'next/image'; import Image from "next/image";
const teamMembers = [ const teamMembers = [
{ {

View File

@ -1,6 +1,7 @@
"use client"; "use client";
import { useMemo, useState } from "react";
import Sidebar from "@/components/Sidebar"; import Sidebar from "@/components/Sidebar";
import { useState, useMemo } from "react";
export default function Warehouse() { export default function Warehouse() {
const [selectedEventId, setSelectedEventId] = useState(""); const [selectedEventId, setSelectedEventId] = useState("");

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import axios from 'axios'; import axios from "axios";
import { FormEvent, MouseEvent, useEffect, useRef, useState } from 'react'; import { FormEvent, MouseEvent, useEffect, useRef, useState } from "react";
interface AuthModalProps { interface AuthModalProps {
isOpen: boolean; // bool for if the modal should be visible isOpen: boolean; // bool for if the modal should be visible

View File

@ -1,13 +1,14 @@
import { useCallback, useState } from "react";
import React, { useRef, useEffect, Dispatch, SetStateAction } from "react";
import mapboxgl, { LngLatBounds } from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css"; import "mapbox-gl/dist/mapbox-gl.css";
import { GiObservatory } from "react-icons/gi";
import Event from "@appTypes/Event"; import mapboxgl, { LngLatBounds } from "mapbox-gl";
import getMagnitudeColor from "@utils/getMagnitudeColour";
import { userAgentFromString } from "next/server"; import { userAgentFromString } from "next/server";
import React, { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import { GiObservatory } from "react-icons/gi";
import Event from "@appTypes/Event";
import getMagnitudeColor from "@utils/getMagnitudeColour";
interface MapComponentProps { interface MapComponentProps {
events: Event[]; events: Event[];
@ -19,7 +20,14 @@ interface MapComponentProps {
} }
// Map component with location-style pulsing dots, animations, and tooltips // Map component with location-style pulsing dots, animations, and tooltips
function MapComponent({ events, selectedEventId, setSelectedEventId, hoveredEventId, setHoveredEventId, mapType }: MapComponentProps) { function MapComponent({
events,
selectedEventId,
setSelectedEventId,
hoveredEventId,
setHoveredEventId,
mapType,
}: MapComponentProps) {
const map = useRef<mapboxgl.Map | null>(null); const map = useRef<mapboxgl.Map | null>(null);
const markers = useRef<{ [key: string]: mapboxgl.Marker }>({}); const markers = useRef<{ [key: string]: mapboxgl.Marker }>({});
const [mapBounds, setMapBounds] = useState<LngLatBounds>(); const [mapBounds, setMapBounds] = useState<LngLatBounds>();
@ -78,7 +86,6 @@ function MapComponent({ events, selectedEventId, setSelectedEventId, hoveredEven
// Add markers with location pulse // Add markers with location pulse
events.forEach((event) => { events.forEach((event) => {
const quakeElement = document.createElement("div"); const quakeElement = document.createElement("div");
const dotElement = document.createElement("div"); const dotElement = document.createElement("div");
const pulseElement = document.createElement("div"); const pulseElement = document.createElement("div");
@ -116,19 +123,19 @@ function MapComponent({ events, selectedEventId, setSelectedEventId, hoveredEven
//<GiObservatory /> //<GiObservatory />
const observatoryElement = document.createElement("div"); const observatoryElement = document.createElement("div");
const root = createRoot(observatoryElement); // `createRoot` is now the standard API const root = createRoot(observatoryElement); // `createRoot` is now the standard API
root.render( root.render(<GiObservatory className="text-blue-600 text-2xl drop-shadow-lg" />);
<GiObservatory className="text-blue-600 text-2xl drop-shadow-lg" />
);
quakeElement.appendChild(pulseElement); quakeElement.appendChild(pulseElement);
quakeElement.appendChild(dotElement); quakeElement.appendChild(dotElement);
const marker = new mapboxgl.Marker({ element: mapType === "observatories" ? observatoryElement : quakeElement }).setLngLat([event.longitude, event.latitude]).addTo(map.current!); const marker = new mapboxgl.Marker({ element: mapType === "observatories" ? observatoryElement : quakeElement })
.setLngLat([event.longitude, event.latitude])
.addTo(map.current!);
const popup = new mapboxgl.Popup({ offset: 25, closeButton: false, anchor: "bottom" }).setHTML(` const popup = new mapboxgl.Popup({ offset: 25, closeButton: false, anchor: "bottom" }).setHTML(`
<div> <div>
<h3>${event.title}</h3> <h3>${event.title}</h3>
${ mapType === "observatories" ? `<p>${event.text1}</p>` : `<p>Magnitude: ${event.magnitude}</p>`} ${mapType === "observatories" ? `<p>${event.text1}</p>` : `<p>Magnitude: ${event.magnitude}</p>`}
<p>${event.text2}</p> <p>${event.text2}</p>
</div> </div>
`); `);
@ -142,7 +149,9 @@ function MapComponent({ events, selectedEventId, setSelectedEventId, hoveredEven
markerDomElement.addEventListener("mouseenter", () => setHoveredEventId(event.id)); markerDomElement.addEventListener("mouseenter", () => setHoveredEventId(event.id));
markerDomElement.addEventListener("mouseleave", () => setHoveredEventId("")); markerDomElement.addEventListener("mouseleave", () => setHoveredEventId(""));
markerDomElement.addEventListener("click", () => setSelectedEventId((prevEventId) => (prevEventId === event.id ? "" : event.id))); markerDomElement.addEventListener("click", () =>
setSelectedEventId((prevEventId) => (prevEventId === event.id ? "" : event.id))
);
// Cleanup event listeners on unmount // Cleanup event listeners on unmount
markerDomElement.dataset.listenersAdded = "true"; // Mark for cleanup markerDomElement.dataset.listenersAdded = "true"; // Mark for cleanup

View File

@ -1,13 +1,13 @@
"use client"; "use client";
import Image from 'next/image'; import Image from "next/image";
import Link from 'next/link'; import Link from "next/link";
import { usePathname } from 'next/navigation'; import { usePathname } from "next/navigation";
import { Dispatch, SetStateAction, useMemo, useState } from 'react'; import { Dispatch, SetStateAction, useMemo, useState } from "react";
import { FaRegUserCircle } from 'react-icons/fa'; import { FaRegUserCircle } from "react-icons/fa";
import { Currency } from '@appTypes/StoreModel'; import { Currency } from "@appTypes/StoreModel";
import AuthModal from '@components/AuthModal'; import AuthModal from "@components/AuthModal";
import { useStoreActions, useStoreState } from '@hooks/store'; import { useStoreActions, useStoreState } from "@hooks/store";
export default function Navbar({}: // currencySelector, export default function Navbar({}: // currencySelector,
{ {

View File

@ -1,3 +1,3 @@
import axios from 'axios'; import axios from "axios";
export const fetcher = (url: string) => axios.get(url).then((res) => res.data); export const fetcher = (url: string) => axios.get(url).then((res) => res.data);

View File

@ -1,5 +1,6 @@
"use client"; "use client";
import resolveConfig from "tailwindcss/resolveConfig"; import resolveConfig from "tailwindcss/resolveConfig";
import tailwindConfig from "../../tailwind.config"; import tailwindConfig from "../../tailwind.config";
function getMagnitudeColour(magnitude: number) { function getMagnitudeColour(magnitude: number) {