Converted to TS, add import
This commit is contained in:
@@ -1,3 +1,33 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--bg: #0a0f1c; /* deep night sky */
|
||||
--surface: #111827; /* panels */
|
||||
--surface-alt: #0f172a; /* slight variation */
|
||||
--text: #e6edf3; /* crisp readable */
|
||||
--muted: #94a3b8; /* secondary text */
|
||||
--accent: #38bdf8; /* sky blue */
|
||||
--accent-soft: #0ea5e9; /* deeper blue */
|
||||
--accent-glow: rgba(56, 189, 248, 0.15);
|
||||
--border: #1f2937;
|
||||
}
|
||||
|
||||
.glass {
|
||||
background: rgba(17, 24, 39, 0.2); /* --surface at 60% */
|
||||
backdrop-filter: blur(12px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(12px) saturate(180%);
|
||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(56, 189, 248, 0.05);
|
||||
}
|
||||
|
||||
.glass-border {
|
||||
border: 1px solid rgba(56, 189, 248, 0.15); /* --accent at low opacity */
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg);
|
||||
background-image:
|
||||
radial-gradient(ellipse at 20% 50%, rgba(56, 189, 248, 0.06) 0%, transparent 60%),
|
||||
radial-gradient(ellipse at 80% 20%, rgba(14, 165, 233, 0.05) 0%, transparent 50%);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="glass-box glass glass-border">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.glass-box {
|
||||
width: 50%;
|
||||
height: 50dvh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap:1em;
|
||||
padding: 2em;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="glass">
|
||||
© FlightsGoneBy. All rights reserved.
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Footer = ~5dvh */
|
||||
footer {
|
||||
flex: 0 0 5dvh;
|
||||
min-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,54 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {Link} from "@inertiajs/vue3";
|
||||
import { usePage } from '@inertiajs/vue3'
|
||||
import type { SharedProps } from '@/Types/types'
|
||||
|
||||
const props = usePage<SharedProps>().props
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="glass">
|
||||
<h1>FlightsGoneBy</h1>
|
||||
<nav>
|
||||
<Link v-if="props.canLogin && !props.auth.user" :href="route('login')">Log In</Link>
|
||||
<Link v-if="props.canRegister && !props.auth.user" :href="route('register')">Register</Link>
|
||||
<Link v-if="props.auth.user">Welcome {{props.auth.user.name}}</Link>
|
||||
</nav>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
header {
|
||||
display:flex;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 5dvh;
|
||||
min-height: 40px; /* prevents it getting too tiny */
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
flex-basis: 25%;
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
header nav{
|
||||
flex-basis: 75%;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 1em;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
header nav a {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,132 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<!-- RadarBackground.vue -->
|
||||
<template>
|
||||
<div class="radar-bg">
|
||||
<svg class="radar-svg" viewBox="0 0 800 420"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<radialGradient id="bgGlow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stop-color="#38bdf8" stop-opacity="0.04"/>
|
||||
<stop offset="100%" stop-color="#0a0f1c" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<clipPath id="radarClip">
|
||||
<circle cx="400" cy="210" r="208"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<!-- Ambient glow -->
|
||||
<ellipse cx="400" cy="210" rx="320" ry="220" fill="url(#bgGlow)"/>
|
||||
|
||||
<!-- Rings -->
|
||||
<circle class="ring" cx="400" cy="210" r="52"/>
|
||||
<circle class="ring" cx="400" cy="210" r="104"/>
|
||||
<circle class="ring" cx="400" cy="210" r="156"/>
|
||||
<circle class="ring" cx="400" cy="210" r="208"/>
|
||||
<circle cx="400" cy="210" r="208" fill="none"
|
||||
stroke="rgba(56,189,248,0.25)" stroke-width="1"/>
|
||||
|
||||
<!-- Crosshairs -->
|
||||
<line class="crosshair" x1="192" y1="210" x2="608" y2="210"/>
|
||||
<line class="crosshair" x1="400" y1="2" x2="400" y2="418"/>
|
||||
<line class="crosshair" x1="253" y1="63" x2="547" y2="357" transform="rotate(45,400,210)"/>
|
||||
<line class="crosshair" x1="253" y1="63" x2="547" y2="357" transform="rotate(-45,400,210)"/>
|
||||
|
||||
<!-- Sweep trail + line -->
|
||||
<g clip-path="url(#radarClip)">
|
||||
<g class="trail">
|
||||
<path d="M400,210 L400,2 A208,208 0 0,1 547,63 Z" fill="rgba(56,189,248,0.08)"/>
|
||||
<path d="M400,210 L400,2 A208,208 0 0,1 493,42 Z" fill="rgba(56,189,248,0.10)"/>
|
||||
<path d="M400,210 L400,2 A208,208 0 0,1 435,4 Z" fill="rgba(56,189,248,0.13)"/>
|
||||
</g>
|
||||
<g class="sweep">
|
||||
<line x1="400" y1="210" x2="400" y2="3"
|
||||
stroke="#38bdf8" stroke-width="1.5" stroke-opacity="0.9"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Blip glows -->
|
||||
<g clip-path="url(#radarClip)">
|
||||
<circle class="blip-glow" cx="470" cy="148" r="8"/>
|
||||
<circle class="blip-glow" cx="340" cy="270" r="8"/>
|
||||
<circle class="blip-glow" cx="510" cy="230" r="8"/>
|
||||
<circle class="blip-glow" cx="378" cy="130" r="8"/>
|
||||
<circle class="blip-glow" cx="430" cy="310" r="8"/>
|
||||
<circle class="blip-glow" cx="290" cy="185" r="8"/>
|
||||
</g>
|
||||
|
||||
<!-- Blips -->
|
||||
<g clip-path="url(#radarClip)">
|
||||
<circle class="blip" cx="470" cy="148" r="2.5"/>
|
||||
<circle class="blip" cx="340" cy="270" r="2.5"/>
|
||||
<circle class="blip" cx="510" cy="230" r="2.5"/>
|
||||
<circle class="blip" cx="378" cy="130" r="2.5"/>
|
||||
<circle class="blip" cx="430" cy="310" r="2.5"/>
|
||||
<circle class="blip" cx="290" cy="185" r="2.5"/>
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
||||
<slot/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* In your component <style> or global CSS */
|
||||
|
||||
.radar-bg {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: var(--bg);
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.radar-svg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity:0.1
|
||||
}
|
||||
|
||||
.ring { fill: none; stroke: rgba(56,189,248,0.12); stroke-width: 1; }
|
||||
.crosshair { stroke: rgba(56,189,248,0.1); stroke-width: 0.5; }
|
||||
.range-label { font-size: 9px; fill: rgba(56,189,248,0.35); font-family: monospace; }
|
||||
|
||||
/* Sweep */
|
||||
.sweep, .trail {
|
||||
transform-origin: 400px 210px;
|
||||
animation: radar-spin 10s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes radar-spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Blips */
|
||||
.blip, .blip-glow {
|
||||
animation: blip-fade 4s linear infinite;
|
||||
}
|
||||
|
||||
.blip { fill: #38bdf8; }
|
||||
.blip-glow { fill: rgba(56,189,248,0.2); }
|
||||
|
||||
@keyframes blip-fade {
|
||||
0% { opacity: 0; }
|
||||
2% { opacity: 1; }
|
||||
60% { opacity: 0.5; }
|
||||
100%{ opacity: 0; }
|
||||
}
|
||||
|
||||
/* Stagger each blip so they don't all pulse together */
|
||||
.blip:nth-child(2), .blip-glow:nth-child(2) { animation-delay: -1.1s; }
|
||||
.blip:nth-child(3), .blip-glow:nth-child(3) { animation-delay: -2.3s; }
|
||||
.blip:nth-child(4), .blip-glow:nth-child(4) { animation-delay: -0.5s; }
|
||||
.blip:nth-child(5), .blip-glow:nth-child(5) { animation-delay: -3.1s; }
|
||||
.blip:nth-child(6), .blip-glow:nth-child(6) { animation-delay: -1.8s; }
|
||||
</style>
|
||||
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import {Link} from "@inertiajs/vue3";
|
||||
import MainHeader from "@/Components/FlightsGoneBy/MainHeader.vue";
|
||||
import MainFooter from "@/Components/FlightsGoneBy/MainFooter.vue";
|
||||
import Radar from "@/Components/FlightsGoneBy/Radar.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Radar>
|
||||
<div class="layoutContainer">
|
||||
<MainHeader />
|
||||
<main id="pageContainer">
|
||||
<slot />
|
||||
</main>
|
||||
<MainFooter />
|
||||
</div>
|
||||
</Radar>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.layoutContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100dvh;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1 0 90dvh; /* THIS is the key */
|
||||
min-height: 0;
|
||||
padding: 1rem;
|
||||
background: var(--surface-alt);
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,32 @@
|
||||
<script setup lang="ts">
|
||||
import MainLayout from "@/Layouts/MainLayout.vue";
|
||||
import GlassBox from "@/Components/FlightsGoneBy/GlassBox.vue";
|
||||
import {Head} from "@inertiajs/vue3";
|
||||
|
||||
defineOptions({
|
||||
layout: MainLayout
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Import" />
|
||||
<GlassBox>
|
||||
<h2>Import Your Flights</h2>
|
||||
<p>
|
||||
Import a CSV export from MyFlightRadar24. You will then be guided to reconcile any data mismatches.
|
||||
</p>
|
||||
<v-file-input style="width:100%; flex:0" label="Select CSV File" accept=".csv" />
|
||||
</GlassBox>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
h2{
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
p{
|
||||
text-align: center;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup>
|
||||
import MainLayout from "@/Layouts/MainLayout.vue";
|
||||
import { Head } from '@inertiajs/vue3';
|
||||
defineOptions({
|
||||
layout: MainLayout
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Home" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
declare global {
|
||||
const route: typeof import('ziggy-js')['route']
|
||||
}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
route: typeof import('ziggy-js')['route']
|
||||
}
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: number
|
||||
name: string
|
||||
email: string
|
||||
email_verified_at: string | null
|
||||
}
|
||||
|
||||
export type SharedProps = import('@inertiajs/core').PageProps & {
|
||||
auth: {
|
||||
user: User | null
|
||||
isLoggedIn: boolean
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@inertiajs/vue3' {
|
||||
interface PageProps extends SharedProps {}
|
||||
}
|
||||
@@ -3,22 +3,24 @@ import './bootstrap';
|
||||
|
||||
import { createInertiaApp } from '@inertiajs/vue3';
|
||||
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
|
||||
import { createApp, h } from 'vue';
|
||||
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
|
||||
import { createApp, h, DefineComponent } from 'vue';
|
||||
import vuetify from './plugins/vuetify';
|
||||
|
||||
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
|
||||
|
||||
createInertiaApp({
|
||||
title: (title) => `${title} - ${appName}`,
|
||||
title: (title) => `${title} | ${appName}`,
|
||||
resolve: (name) =>
|
||||
resolvePageComponent(
|
||||
`./Pages/${name}.vue`,
|
||||
import.meta.glob('./Pages/**/*.vue'),
|
||||
import.meta.glob<DefineComponent>('./Pages/**/*.vue'),
|
||||
),
|
||||
setup({ el, App, props, plugin }) {
|
||||
return createApp({ render: () => h(App, props) })
|
||||
.use(plugin)
|
||||
.use(ZiggyVue)
|
||||
.use(vuetify)
|
||||
.mount(el);
|
||||
},
|
||||
progress: {
|
||||
@@ -0,0 +1,8 @@
|
||||
import 'vuetify/styles'
|
||||
import { createVuetify } from 'vuetify'
|
||||
|
||||
export default createVuetify({
|
||||
theme: {
|
||||
defaultTheme: 'dark',
|
||||
},
|
||||
})
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.css'
|
||||
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
/* This file is generated by Ziggy. */
|
||||
declare module 'ziggy-js' {
|
||||
interface RouteList {
|
||||
"dashboard": [],
|
||||
"profile.edit": [],
|
||||
"profile.update": [],
|
||||
"profile.destroy": [],
|
||||
"register": [],
|
||||
"login": [],
|
||||
"password.request": [],
|
||||
"password.email": [],
|
||||
"password.reset": [
|
||||
{
|
||||
"name": "token",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"password.store": [],
|
||||
"verification.notice": [],
|
||||
"verification.verify": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "hash",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"verification.send": [],
|
||||
"password.confirm": [],
|
||||
"password.update": [],
|
||||
"logout": [],
|
||||
"sanctum.csrf-cookie": [],
|
||||
"storage.local": [
|
||||
{
|
||||
"name": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"storage.local.upload": [
|
||||
{
|
||||
"name": "path",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
const Ziggy = {"url":"http:\/\/localhost:8000","port":8000,"defaults":{},"routes":{"dashboard":{"uri":"dashboard","methods":["GET","HEAD"],"domain":"flightsgoneby.test"},"profile.edit":{"uri":"profile","methods":["GET","HEAD"],"domain":"flightsgoneby.test"},"profile.update":{"uri":"profile","methods":["PATCH"],"domain":"flightsgoneby.test"},"profile.destroy":{"uri":"profile","methods":["DELETE"],"domain":"flightsgoneby.test"},"register":{"uri":"register","methods":["GET","HEAD"],"domain":"flightsgoneby.test"},"login":{"uri":"login","methods":["GET","HEAD"],"domain":"flightsgoneby.test"},"password.request":{"uri":"forgot-password","methods":["GET","HEAD"],"domain":"flightsgoneby.test"},"password.email":{"uri":"forgot-password","methods":["POST"],"domain":"flightsgoneby.test"},"password.reset":{"uri":"reset-password\/{token}","methods":["GET","HEAD"],"domain":"flightsgoneby.test","parameters":["token"]},"password.store":{"uri":"reset-password","methods":["POST"],"domain":"flightsgoneby.test"},"verification.notice":{"uri":"verify-email","methods":["GET","HEAD"],"domain":"flightsgoneby.test"},"verification.verify":{"uri":"verify-email\/{id}\/{hash}","methods":["GET","HEAD"],"domain":"flightsgoneby.test","parameters":["id","hash"]},"verification.send":{"uri":"email\/verification-notification","methods":["POST"],"domain":"flightsgoneby.test"},"password.confirm":{"uri":"confirm-password","methods":["GET","HEAD"],"domain":"flightsgoneby.test"},"password.update":{"uri":"password","methods":["PUT"],"domain":"flightsgoneby.test"},"logout":{"uri":"logout","methods":["POST"],"domain":"flightsgoneby.test"},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"storage.local":{"uri":"storage\/{path}","methods":["GET","HEAD"],"wheres":{"path":".*"},"parameters":["path"]},"storage.local.upload":{"uri":"storage\/{path}","methods":["PUT"],"wheres":{"path":".*"},"parameters":["path"]}}};
|
||||
if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') {
|
||||
Object.assign(Ziggy.routes, window.Ziggy.routes);
|
||||
}
|
||||
export { Ziggy };
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<!-- Scripts -->
|
||||
@routes
|
||||
@vite(['resources/js/app.js', "resources/js/Pages/{$page['component']}.vue"])
|
||||
@vite(['resources/js/app.ts', "resources/js/Pages/{$page['component']}.vue"])
|
||||
@inertiaHead
|
||||
</head>
|
||||
<body class="font-sans antialiased">
|
||||
|
||||
Reference in New Issue
Block a user