add potus tracker
This commit is contained in:
parent
0a0ff32921
commit
2941679974
148
package-lock.json
generated
148
package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"https": "^1.0.0",
|
||||
"jsconfig.json": "^2.3.3",
|
||||
"ol": "^10.3.1",
|
||||
"plotly.js": "^2.35.3",
|
||||
"svelte-plotly.js": "^1.2.0",
|
||||
"ua-parser-js": "^1.0.37"
|
||||
@ -1234,6 +1235,12 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@petamoriken/float16": {
|
||||
"version": "3.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.1.tgz",
|
||||
"integrity": "sha512-j+ejhYwY6PeB+v1kn7lZFACUIG97u90WxMuGosILFsl9d4Ovi0sjk0GlPfoEcx+FzvXZDAfioD+NGnnPamXgMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
@ -2385,6 +2392,12 @@
|
||||
"integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/rbush": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-4.0.0.tgz",
|
||||
"integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
@ -5036,6 +5049,37 @@
|
||||
"integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/geotiff": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.1.3.tgz",
|
||||
"integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@petamoriken/float16": "^3.4.7",
|
||||
"lerc": "^3.0.0",
|
||||
"pako": "^2.0.4",
|
||||
"parse-headers": "^2.0.2",
|
||||
"quick-lru": "^6.1.1",
|
||||
"web-worker": "^1.2.0",
|
||||
"xml-utils": "^1.0.2",
|
||||
"zstddec": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19"
|
||||
}
|
||||
},
|
||||
"node_modules/geotiff/node_modules/quick-lru": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz",
|
||||
"integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
@ -6271,6 +6315,12 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/lerc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz",
|
||||
"integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/lightweight-charts": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lightweight-charts/-/lightweight-charts-4.1.3.tgz",
|
||||
@ -7033,6 +7083,59 @@
|
||||
"integrity": "sha512-QiM9D0NiU5jV6J6tjE1g7b4Z2tcUnKs1OPUi4iMb2zH+7jwlcUrASghgkFk9GtzqNNq8rTQJtT8AzjBAvLoNMw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ol": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ol/-/ol-10.3.1.tgz",
|
||||
"integrity": "sha512-D1nRQVLOBCRempVqBFV8pSI5H13BtnhuLDjGl+3NKdMOFyjx/UqRX/tcMspEw3LhFOSPWn1Ev+1KIRV8AlHM7A==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@types/rbush": "4.0.0",
|
||||
"color-rgba": "^3.0.0",
|
||||
"color-space": "^2.0.1",
|
||||
"earcut": "^3.0.0",
|
||||
"geotiff": "^2.1.3",
|
||||
"pbf": "4.0.1",
|
||||
"rbush": "^4.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/openlayers"
|
||||
}
|
||||
},
|
||||
"node_modules/ol/node_modules/color-rgba": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-3.0.0.tgz",
|
||||
"integrity": "sha512-PPwZYkEY3M2THEHHV6Y95sGUie77S7X8v+h1r6LSAPF3/LL2xJ8duUXSrkic31Nzc4odPwHgUbiX/XuTYzQHQg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-parse": "^2.0.0",
|
||||
"color-space": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ol/node_modules/color-space": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/color-space/-/color-space-2.1.0.tgz",
|
||||
"integrity": "sha512-zVS/1YXvFB4AoYqpKzcQ694s7dOKXHtSbQfcfuxeuTr4oE1U40zkrqvyEsu8OD9e2pTuGjfRFNUR2Ii4XkoE9w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ol/node_modules/earcut": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz",
|
||||
"integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ol/node_modules/pbf": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz",
|
||||
"integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"resolve-protobuf-schema": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"pbf": "bin/pbf"
|
||||
}
|
||||
},
|
||||
"node_modules/on-headers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||
@ -7112,6 +7215,12 @@
|
||||
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/parchment": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz",
|
||||
@ -7124,6 +7233,12 @@
|
||||
"integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/parse-headers": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz",
|
||||
"integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/parse-rect": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-rect/-/parse-rect-1.2.0.tgz",
|
||||
@ -7860,6 +7975,21 @@
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rbush": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rbush/-/rbush-4.0.1.tgz",
|
||||
"integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"quickselect": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rbush/node_modules/quickselect": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz",
|
||||
"integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
@ -9950,6 +10080,12 @@
|
||||
"integrity": "sha512-lNR9aAefbGPpHO7AEnY0hCFjz1eTkWCXYvkTRrTHs9qv8zJp+SkVYpzfLIFXQQiG3tVvbNFQgVg2bQS8YGgxyw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/web-worker": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz",
|
||||
"integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/webgl-context": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/webgl-context/-/webgl-context-2.2.0.tgz",
|
||||
@ -10143,6 +10279,12 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/xml-utils": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.1.tgz",
|
||||
"integrity": "sha512-Dn6vJ1Z9v1tepSjvnCpwk5QqwIPcEFKdgnjqfYOABv1ngSofuAhtlugcUC3ehS1OHdgDWSG6C5mvj+Qm15udTQ==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
@ -10241,6 +10383,12 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/zstddec": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz",
|
||||
"integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==",
|
||||
"license": "MIT AND BSD-3-Clause"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +95,7 @@
|
||||
"dependencies": {
|
||||
"https": "^1.0.0",
|
||||
"jsconfig.json": "^2.3.3",
|
||||
"ol": "^10.3.1",
|
||||
"plotly.js": "^2.35.3",
|
||||
"svelte-plotly.js": "^1.2.0",
|
||||
"ua-parser-js": "^1.0.37"
|
||||
|
||||
118
src/lib/components/Map.svelte
Normal file
118
src/lib/components/Map.svelte
Normal file
@ -0,0 +1,118 @@
|
||||
<script>
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import { browser } from "$app/environment";
|
||||
import "ol/ol.css";
|
||||
import Map from "ol/Map";
|
||||
import View from "ol/View";
|
||||
import TileLayer from "ol/layer/Tile";
|
||||
import XYZ from "ol/source/XYZ";
|
||||
import { fromLonLat } from "ol/proj";
|
||||
import VectorLayer from "ol/layer/Vector";
|
||||
import VectorSource from "ol/source/Vector";
|
||||
import Feature from "ol/Feature";
|
||||
import Point from "ol/geom/Point";
|
||||
import { Style, Circle, Fill } from "ol/style";
|
||||
|
||||
// White House coordinates
|
||||
const LON = -77.0365427;
|
||||
const LAT = 38.8950368;
|
||||
const ZOOM = 5;
|
||||
|
||||
let mapElement;
|
||||
let map;
|
||||
let animationFrame;
|
||||
let pulseProgress = 0;
|
||||
|
||||
// Pulsing style function
|
||||
const createPulseStyle = (progress) => {
|
||||
return new Style({
|
||||
image: new Circle({
|
||||
radius: 6 + 9 * progress,
|
||||
fill: new Fill({
|
||||
color: `rgba(46, 134, 222, ${0.3 - 0.3 * progress})`,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
// Animation loop
|
||||
const animate = () => {
|
||||
pulseProgress = (pulseProgress + 0.02) % 1;
|
||||
vectorLayer
|
||||
.getSource()
|
||||
.getFeatures()[0]
|
||||
.setStyle([
|
||||
new Style({
|
||||
image: new Circle({
|
||||
radius: 6,
|
||||
fill: new Fill({
|
||||
color: "#2e86de",
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
createPulseStyle(pulseProgress),
|
||||
]);
|
||||
animationFrame = requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
let vectorLayer;
|
||||
|
||||
onMount(() => {
|
||||
if (!browser) return;
|
||||
|
||||
const whiteHousePoint = new Feature({
|
||||
geometry: new Point(fromLonLat([LON, LAT])),
|
||||
});
|
||||
|
||||
vectorLayer = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [whiteHousePoint],
|
||||
}),
|
||||
});
|
||||
|
||||
map = new Map({
|
||||
target: mapElement,
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new XYZ({
|
||||
url: "https://{a-d}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
|
||||
attributions:
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||
}),
|
||||
}),
|
||||
vectorLayer,
|
||||
],
|
||||
view: new View({
|
||||
center: fromLonLat([LON, LAT]),
|
||||
zoom: ZOOM,
|
||||
minZoom: 2,
|
||||
maxZoom: 18,
|
||||
}),
|
||||
controls: [],
|
||||
});
|
||||
|
||||
animate();
|
||||
|
||||
return () => {
|
||||
if (map) map.setTarget(undefined);
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div bind:this={mapElement} class="map-container" />
|
||||
|
||||
<style>
|
||||
.map-container {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
background-color: #1a1a1a;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.map-container {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -662,19 +662,19 @@
|
||||
>Reddit Tracker</a
|
||||
>
|
||||
</Button>
|
||||
<!--
|
||||
|
||||
<Button
|
||||
builders={[builder]}
|
||||
type="submit"
|
||||
class="w-full bg-[#141417] hover:bg-[#141417]"
|
||||
>
|
||||
<a
|
||||
href="/corporate-lobbying-tracker"
|
||||
href="/potus-tracker"
|
||||
class="text-start w-full text-[1rem] text-white ml-4 mt-4"
|
||||
>Lobbying Tracker</a
|
||||
>Potus Tracker</a
|
||||
>
|
||||
</Button>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<Button
|
||||
builders={[builder]}
|
||||
@ -1124,13 +1124,13 @@
|
||||
class="text-[1rem] text-white ml-4 mt-4"
|
||||
>Reddit Tracker</a
|
||||
>
|
||||
<!--
|
||||
|
||||
<a
|
||||
href="/corporate-lobbying-tracker"
|
||||
href="/potus-tracker"
|
||||
class="text-[1rem] text-white ml-4 mt-4"
|
||||
>Lobbying Tracker</a
|
||||
>Potus Tracker</a
|
||||
>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<a
|
||||
href="/sentiment-tracker"
|
||||
|
||||
@ -125,13 +125,11 @@
|
||||
class="text-center mb-10 relative w-fit flex justify-center m-auto text-white"
|
||||
>
|
||||
<div class="mb-4 flex justify-center -mt-3 lg:mb-8">
|
||||
<a href="/stocks/NVDA/options/unusual-activity"
|
||||
<a href="/heatmap"
|
||||
><div
|
||||
class="flex items-center justify-center sm:hover:text-white text-blue-400"
|
||||
>
|
||||
<div class="text-lg sm:text-xl font-semibold">
|
||||
Unusual Activity
|
||||
</div>
|
||||
<div class="text-lg sm:text-xl font-semibold">S&P500 Heatmap</div>
|
||||
<div
|
||||
class="-mt-2 ml-1 -rotate-6 rounded-lg bg-red-500 px-1 py-0.5 text-xs font-semibold text-white"
|
||||
>
|
||||
|
||||
23
src/routes/potus-tracker/+page.server.ts
Normal file
23
src/routes/potus-tracker/+page.server.ts
Normal file
@ -0,0 +1,23 @@
|
||||
export const load = async ({ locals, setHeaders }) => {
|
||||
const getData = async () => {
|
||||
const { apiKey, apiURL, user } = locals;
|
||||
|
||||
// make the POST request to the endpoint
|
||||
const response = await fetch(apiURL + "/potus-tracker", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-API-KEY": apiKey,
|
||||
},
|
||||
});
|
||||
|
||||
const output = await response.json();
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
// Make sure to return a promise
|
||||
return {
|
||||
getData: await getData(),
|
||||
};
|
||||
};
|
||||
219
src/routes/potus-tracker/+page.svelte
Normal file
219
src/routes/potus-tracker/+page.svelte
Normal file
@ -0,0 +1,219 @@
|
||||
<script lang="ts">
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
import Map from "$lib/components/Map.svelte";
|
||||
|
||||
export let data;
|
||||
|
||||
let rawData = data?.getData?.history || [];
|
||||
let billData = data?.getData?.billData || [];
|
||||
|
||||
const groupedByDate = rawData?.reduce((acc, item) => {
|
||||
const dateKey = new Intl.DateTimeFormat("en-US", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
}).format(new Date(item.date));
|
||||
|
||||
if (!acc[dateKey]) acc[dateKey] = [];
|
||||
acc[dateKey].push(item);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
let modalTitle = "n/a";
|
||||
let modalDescription = "n/a";
|
||||
</script>
|
||||
|
||||
<SEO
|
||||
title="POTUS Tracker - Executive Orders, Presidential Schedule, Signed Legislation"
|
||||
description="Where is the President? Find out what the President of the United States is doing with real-time location, schedule, legislation, and executive order updates."
|
||||
/>
|
||||
|
||||
<section
|
||||
class="w-full max-w-3xl sm:max-w-[1400px] overflow-hidden min-h-screen pb-20 pt-5 px-4 lg:px-3 text-white"
|
||||
>
|
||||
<div class="text-sm sm:text-[1rem] breadcrumbs">
|
||||
<ul>
|
||||
<li><a href="/" class="text-gray-300">Home</a></li>
|
||||
<li class="text-gray-300">POTUS Tracker</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="w-full flex h-full overflow-hidden">
|
||||
<div
|
||||
class="w-full relative flex justify-center items-center overflow-hidden"
|
||||
>
|
||||
<div
|
||||
class="relative flex flex-row justify-center items-start overflow-hidden w-full"
|
||||
>
|
||||
<div class="w-full mt-5">
|
||||
<div class="lg:float-left lg:w-[calc(100%-336px-20px)]">
|
||||
<h1 class="text-xl sm:text-2xl font-bold mb-4 w-full">
|
||||
POTUS Tracker
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class=" mb-2 lg:float-left lg:w-[calc(100%-336px-40px)]">
|
||||
<h2 class="text-white text-xl font-semibold mb-2">
|
||||
The US President is in {data?.getData?.city ?? "n/a"}
|
||||
</h2>
|
||||
|
||||
<div class="w-full m-auto border border-gray-800 rounded-[10px]">
|
||||
<Map LAT={data?.getData?.lat} LON={data?.getData?.lon} />
|
||||
</div>
|
||||
|
||||
<h3 class="text-white text-xl font-semibold mb-2 mt-10">
|
||||
Official Presidential Schedule
|
||||
</h3>
|
||||
|
||||
<div class="space-y-4">
|
||||
{#each Object.entries(groupedByDate) as [date, items], indexA}
|
||||
<div class="my-4">
|
||||
<div
|
||||
class="border-b border-gray-800 pb-2 text-lg font-semibold text-white"
|
||||
>
|
||||
{date}
|
||||
</div>
|
||||
<!-- Display date -->
|
||||
<br />
|
||||
{#each items as item, indexB}
|
||||
<div class="flex flex-col items-start space-y-1 mb-6">
|
||||
<div class="flex flex-row items-center space-x-2">
|
||||
<div class="relative">
|
||||
<svg
|
||||
fill={indexA === 0 && indexB === 0
|
||||
? "#2E86DE"
|
||||
: "#808080"}
|
||||
class="w-5 h-5 relative z-10"
|
||||
viewBox="-51.2 -51.2 614.40 614.40"
|
||||
id="_78_Circle-Full"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
stroke={indexA === 0 && indexB === 0
|
||||
? "#2E86DE"
|
||||
: "#808080"}
|
||||
stroke-width="0.00512"
|
||||
>
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||
<g
|
||||
id="SVGRepo_tracerCarrier"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke="#CCCCCC"
|
||||
stroke-width="24.576"
|
||||
></g>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<path
|
||||
id="Path_111"
|
||||
data-name="Path 111"
|
||||
d="M256,512C114.625,512,0,397.375,0,256S114.625,0,256,0,512,114.625,512,256,397.375,512,256,512Zm0-448C149.969,64,64,149.969,64,256s85.969,192,192,192,192-85.969,192-192S362.031,64,256,64Zm0,320A128,128,0,1,1,384,256,128.006,128.006,0,0,1,256,384Z"
|
||||
fill-rule="evenodd"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{#if indexA === 0 && indexB === 0}
|
||||
<span
|
||||
class="absolute -inset-1 rounded-full animate-ping w-3 h-3 m-auto bg-blue-400/75"
|
||||
></span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<span class="text-sm text-gray-400">
|
||||
{item.time_formatted} - {item.location}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span class="text-sm ml-7">
|
||||
{item.details}
|
||||
</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="order-4 flex-shrink-0 lg:float-right lg:w-[336px]">
|
||||
<h3 class="text-xl text-white font-semibold mb-3">
|
||||
Latest Legislations
|
||||
</h3>
|
||||
<div class="overflow-y-auto max-h-[1000px]">
|
||||
{#each billData as item}
|
||||
<div class="bg-gray-800/50 rounded-lg p-4 mb-4">
|
||||
<!-- Badge and Time -->
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<span
|
||||
class="bg-emerald-500 text-white px-4 py-1 rounded text-sm font-medium"
|
||||
>
|
||||
{item?.badge}
|
||||
</span>
|
||||
<span class="text-gray-400 text-sm"
|
||||
>{item?.time !== null ? item?.time : ""}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<h2 class="text-[#E5E7EB] text-lg font-semibold mb-3">
|
||||
{item?.title}
|
||||
</h2>
|
||||
|
||||
<!-- Description -->
|
||||
<p class="text-gray-400 text-sm mb-4">
|
||||
{item?.description?.length > 150
|
||||
? item?.description?.slice(0, 150) + "..."
|
||||
: item?.description}
|
||||
</p>
|
||||
|
||||
<!-- Read More Button -->
|
||||
<div class="flex justify-end">
|
||||
<label
|
||||
on:click={() => {
|
||||
modalTitle = item?.title;
|
||||
modalDescription = item?.description;
|
||||
}}
|
||||
for="readMore"
|
||||
class="cursor-pointer bg-blue-500 sm:hover:bg-blue-600 ease-out transition duration-100 text-white px-3 py-1.5 rounded text-sm"
|
||||
>
|
||||
Read More
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Desktop modal using dialog component -->
|
||||
<input type="checkbox" id="readMore" class="modal-toggle" />
|
||||
|
||||
<dialog id="readMore" class="modal p-3 sm:p-0">
|
||||
<label
|
||||
for="readMore"
|
||||
class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.8]"
|
||||
></label>
|
||||
|
||||
<!-- Desktop modal content -->
|
||||
<div
|
||||
class="modal-box rounded-md border border-gray-600 w-full bg-secondary flex flex-col items-center"
|
||||
>
|
||||
<div class="mx-auto h-1.5 w-20 flex-shrink-0 rounded-full" />
|
||||
<div class="text-white mb-5 text-center">
|
||||
<h3 class="font-bold text-xl mb-5">{modalTitle}</h3>
|
||||
<span class="text-white text-[1rem] font-normal"
|
||||
>{@html modalDescription}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-600 mt-2 w-full">
|
||||
<label
|
||||
for="readMore"
|
||||
class="mt-4 font-semibold text-white text-xl m-auto flex justify-center cursor-pointer"
|
||||
>
|
||||
Close
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
@ -1,10 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
stockTicker,
|
||||
displayCompanyName,
|
||||
numberOfUnreadNotification,
|
||||
} from "$lib/store";
|
||||
import { stockTicker, displayCompanyName } from "$lib/store";
|
||||
import { sectorNavigation } from "$lib/utils";
|
||||
import SEO from "$lib/components/SEO.svelte";
|
||||
|
||||
export let data;
|
||||
|
||||
@ -43,43 +40,10 @@ ${paragraphs.join("\n")}
|
||||
);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>
|
||||
{$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""}
|
||||
{$displayCompanyName} ({$stockTicker?.toUpperCase()}) Company Profile &
|
||||
Overview · Stocknear
|
||||
</title>
|
||||
|
||||
<meta
|
||||
name="description"
|
||||
content={`Company profile for ${$displayCompanyName} (${$stockTicker?.toUpperCase()}) with a description, list of executives, contact details and other key facts.`}
|
||||
/>
|
||||
<!-- Other meta tags -->
|
||||
<meta
|
||||
property="og:title"
|
||||
content={`${$displayCompanyName} (${$stockTicker?.toUpperCase()}) Company Profile & Overview · Stocknear`}
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content={`Company profile for ${$displayCompanyName} (${$stockTicker?.toUpperCase()}) with a description, list of executives, contact details and other key facts.`}
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<!-- Add more Open Graph meta tags as needed -->
|
||||
|
||||
<!-- Twitter specific meta tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content={`${$displayCompanyName} (${$stockTicker?.toUpperCase()}) Company Profile & Overview · Stocknear`}
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content={`Company profile for ${$displayCompanyName} (${$stockTicker?.toUpperCase()}) with a description, list of executives, contact details and other key facts.`}
|
||||
/>
|
||||
<!-- Add more Twitter meta tags as needed -->
|
||||
</svelte:head>
|
||||
<SEO
|
||||
title={`${$displayCompanyName} (${$stockTicker?.toUpperCase()}) Company Profile & Overview`}
|
||||
description={`Company profile for ${$displayCompanyName} (${$stockTicker?.toUpperCase()}) with a description, list of executives, contact details and other key facts.`}
|
||||
/>
|
||||
|
||||
<section class="w-full bg-default overflow-hidden text-white h-full">
|
||||
<div class="w-full flex h-full overflow-hidden">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user