Make UI better (WIP)

This commit is contained in:
Mason Mirabile 2026-04-21 13:44:19 +02:00
parent e26d4879e8
commit 898d5c5af3
4 changed files with 317 additions and 26 deletions

View file

@ -6,6 +6,89 @@
<svelte:head>
<link rel="icon" href={favicon} />
<title>City Portal</title>
</svelte:head>
<div class="app">
<header class="header">
<div class="brand">
<img src={favicon} alt="logo" class="logo" />
<span>City Portal</span>
</div>
</header>
<main class="content">
{@render children()}
</main>
</div>
<style>
/* Reset + base */
.app {
min-height: 100vh;
display: flex;
flex-direction: column;
background: #ffffff;
color: #111827;
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
}
/* Header */
.header {
display: flex;
align-items: center;
padding: 14px 24px;
border-bottom: 1px solid #e5e7eb;
background: #ffffff;
}
.brand {
display: flex;
align-items: center;
gap: 10px;
font-weight: 600;
font-size: 16px;
}
.logo {
width: 20px;
height: 20px;
}
/* Content */
.content {
flex: 1;
padding: 24px;
max-width: 1000px;
width: 100%;
margin: 0 auto;
}
/* Fix ugly default link colors */
a {
color: #2563eb;
text-decoration: none;
}
a:visited {
color: #2563eb;
}
a:hover {
text-decoration: underline;
}
/* Optional: make buttons consistent if you use them */
button {
background: #2563eb;
color: white;
border: none;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
}
button:hover {
background: #1d4ed8;
}
</style>

View file

@ -1,7 +1,66 @@
<h1>Welcome to the City Portal!</h1>
<script lang="ts">
// no logic needed yet
</script>
<ul>
<li><a href="datasets/">List of datasets</a></li>
<li><a href="about/">Read about the project!</a></li>
<li><a href="http://localhost:3000/graphiql">Directly interface with the backend</a></li>
<main class="container">
<h1>City Portal</h1>
<p class="subtitle">Access datasets, learn about the project, or explore the API.</p>
<nav>
<ul class="links">
<li>
<a href="/datasets">📊 Datasets</a>
</li>
<li>
<a href="/about"> About the project</a>
</li>
<li>
<a href="http://localhost:3000/graphiql" target="_blank" rel="noopener">
🧪 GraphiQL interface
</a>
</li>
</ul>
</nav>
</main>
<style>
.container {
max-width: 700px;
margin: 4rem auto;
padding: 0 1rem;
text-align: center;
}
h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
.subtitle {
color: #94a3b8;
margin-bottom: 2rem;
}
.links {
list-style: none;
padding: 0;
display: flex;
flex-direction: column;
gap: 1rem;
}
.links a {
display: block;
padding: 1rem;
border-radius: 0.75rem;
background: #1e293b;
color: #e2e8f0;
text-decoration: none;
transition: transform 0.15s ease, background 0.15s ease;
}
.links a:hover {
background: #334155;
transform: translateY(-2px);
}
</style>

View file

@ -1,26 +1,122 @@
<script lang="ts">
import type { PageProps } from "./$types";
import { goto } from "$app/navigation";
let { data }: PageProps = $props();
function getIcon(name: string) {
switch (name) {
case "Weather":
return "☀️";
case "Transport":
return "🚌";
case "Events":
return "🎟️";
case "News":
return "📰";
case "Shops":
return "🏪";
case "Alerts":
return "⚠️";
case "Sports":
return "⚽";
default:
return "📊";
}
}
</script>
<svelte:head>
<title>List of datasets</title>
<title>City Dashboard</title>
</svelte:head>
{#if data.datasets.length}
<div class="grid">
{#each data.datasets as dataset}
<nav>
<ul>
<li>
<a href="datasets/{dataset.id}"><strong>{dataset.name}</strong></a><br
/>
<div class="card">
<button
class="dataset-btn"
on:click={() => goto(`/datasets/${dataset.id}`)}
>
<div class="icon">{getIcon(dataset.name)}</div>
<div class="name">{dataset.name}</div>
</button>
<div class="desc">
{dataset.description}
</li>
</ul>
</nav>
</div>
</div>
{/each}
</div>
{:else}
<h1>No datasets yet!</h1>
<p>Try adding a dataset through the backend.</p>
{/if}
<style>
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 18px;
margin-top: 24px;
}
@media (max-width: 900px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 500px) {
.grid {
grid-template-columns: 1fr;
}
}
.card {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.dataset-btn {
width: 100%;
background: #071a33;
color: white;
border: none;
padding: 26px 16px;
border-radius: 12px;
cursor: pointer;
font-size: 16px;
font-weight: 700;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
transition: background 0.2s, transform 0.1s;
}
.dataset-btn:hover {
background: #0b2a52;
transform: translateY(-3px);
}
.dataset-btn:active {
transform: translateY(0px);
}
.icon {
font-size: 28px;
}
.name {
font-size: 16px;
}
.desc {
margin-top: 8px;
font-size: 13px;
color: #6b7280;
}
</style>

View file

@ -3,14 +3,67 @@
let { data }: PageProps = $props();
// svelte-ignore state_referenced_locally
const recordData = JSON.parse(data.record.data);
</script>
<h1>Data for record id: {data.record.id}</h1>
<svelte:head>
<title>Record {data.record.id}</title>
</svelte:head>
<ul>
<div class="container">
<h1 class="title">Record #{data.record.id}</h1>
<div class="grid">
{#each Object.entries(recordData) as [key, value]}
<li>{key}: {value}</li>
<div class="card">
<div class="key">{key}</div>
<div class="value">
{Array.isArray(value) ? value.join(", ") : value}
</div>
</div>
{/each}
</ul>
</div>
</div>
<style>
.container {
max-width: 900px;
margin: 0 auto;
padding: 24px;
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
}
.title {
font-size: 24px;
font-weight: 700;
margin-bottom: 20px;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 12px;
}
.card {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 10px;
padding: 14px;
}
.key {
font-size: 12px;
text-transform: uppercase;
color: #6b7280;
margin-bottom: 6px;
letter-spacing: 0.5px;
}
.value {
font-size: 15px;
font-weight: 600;
color: #111827;
word-break: break-word;
}
</style>