mirror of
https://github.com/System-End/APCSA-Final.git
synced 2026-04-19 15:18:20 +00:00
feat: scaffold spring boot web app with nasa apod
This commit is contained in:
parent
f60d4161e7
commit
398d0370e6
11 changed files with 376 additions and 2 deletions
6
.env.example
Normal file
6
.env.example
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Copy this file to .env and fill in real values.
|
||||
|
||||
NASA_API_KEY=YOUR_NASA_API_KEY
|
||||
ASTRONOMY_API_APP_ID=YOUR_ASTRONOMY_API_APP_ID
|
||||
ASTRONOMY_API_APP_SECRET=YOUR_ASTRONOMY_API_APP_SECRET
|
||||
PORT=8080
|
||||
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Maven / Java build output
|
||||
target/
|
||||
*.class
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# IDE files
|
||||
.idea/
|
||||
.vscode/
|
||||
.settings/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Local secrets / env
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
src/main/resources/application-local.properties
|
||||
src/main/resources/secrets.properties
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2026 End Nightshade
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
28
README.md
28
README.md
|
|
@ -1,2 +1,26 @@
|
|||
# APCSA-Final
|
||||
Final for APCSA
|
||||
# APCSA Final Project
|
||||
|
||||
Space Mission and Event Tracker (website, with possible mobile app version later).
|
||||
|
||||
## What it does
|
||||
- Pulls live data from space APIs
|
||||
- Lets users search/filter missions and events
|
||||
|
||||
## APIs
|
||||
- The Space Devs Launch Library 2
|
||||
- NASA Open APIs
|
||||
- AstronomyAPI
|
||||
|
||||
## Tech
|
||||
- Java 21
|
||||
- Spring Boot + Thymeleaf
|
||||
- Maven
|
||||
- Mobile app version (possible future phase)
|
||||
|
||||
## Goal
|
||||
Make space mission + astronomy event info easy to view in one place.
|
||||
|
||||
## Run locally
|
||||
- Put your NASA key in `.env` or export `NASA_API_KEY`
|
||||
- Start app: `mvn spring-boot:run`
|
||||
- Open: `http://localhost:8080`
|
||||
|
|
|
|||
48
pom.xml
Normal file
48
pom.xml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.3.5</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.apcsa</groupId>
|
||||
<artifactId>space-tracker</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>space-tracker</name>
|
||||
<description>APCSA final project: Space Mission and Event Tracker</description>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.apcsa.spacetracker;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpaceTrackerApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpaceTrackerApplication.class, args);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.apcsa.spacetracker.controller;
|
||||
|
||||
import com.apcsa.spacetracker.model.ApodResponse;
|
||||
import com.apcsa.spacetracker.service.NasaService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
private final NasaService nasaService;
|
||||
|
||||
public HomeController(NasaService nasaService) {
|
||||
this.nasaService = nasaService;
|
||||
}
|
||||
|
||||
@GetMapping("/")
|
||||
public String home(Model model) {
|
||||
try {
|
||||
ApodResponse apod = nasaService.getApod();
|
||||
model.addAttribute("apod", apod);
|
||||
} catch (Exception ex) {
|
||||
model.addAttribute("error", "Could not load NASA APOD right now.");
|
||||
}
|
||||
|
||||
return "index";
|
||||
}
|
||||
}
|
||||
58
src/main/java/com/apcsa/spacetracker/model/ApodResponse.java
Normal file
58
src/main/java/com/apcsa/spacetracker/model/ApodResponse.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package com.apcsa.spacetracker.model;
|
||||
|
||||
public class ApodResponse {
|
||||
private String title;
|
||||
private String date;
|
||||
private String explanation;
|
||||
private String url;
|
||||
private String hdurl;
|
||||
private String media_type;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(String date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getExplanation() {
|
||||
return explanation;
|
||||
}
|
||||
|
||||
public void setExplanation(String explanation) {
|
||||
this.explanation = explanation;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getHdurl() {
|
||||
return hdurl;
|
||||
}
|
||||
|
||||
public void setHdurl(String hdurl) {
|
||||
this.hdurl = hdurl;
|
||||
}
|
||||
|
||||
public String getMedia_type() {
|
||||
return media_type;
|
||||
}
|
||||
|
||||
public void setMedia_type(String media_type) {
|
||||
this.media_type = media_type;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.apcsa.spacetracker.service;
|
||||
|
||||
import com.apcsa.spacetracker.model.ApodResponse;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
@Service
|
||||
public class NasaService {
|
||||
private final RestTemplate restTemplate;
|
||||
private final String nasaApiKey;
|
||||
|
||||
public NasaService(@Value("${nasa.api.key}") String nasaApiKey) {
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.nasaApiKey = nasaApiKey;
|
||||
}
|
||||
|
||||
public ApodResponse getApod() {
|
||||
String url = UriComponentsBuilder
|
||||
.fromHttpUrl("https://api.nasa.gov/planetary/apod")
|
||||
.queryParam("api_key", nasaApiKey)
|
||||
.toUriString();
|
||||
|
||||
return restTemplate.getForObject(url, ApodResponse.class);
|
||||
}
|
||||
}
|
||||
5
src/main/resources/application.properties
Normal file
5
src/main/resources/application.properties
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
spring.application.name=space-tracker
|
||||
server.port=${PORT:8080}
|
||||
|
||||
# Pull from environment variables; safe defaults for local dev.
|
||||
nasa.api.key=${NASA_API_KEY:DEMO_KEY}
|
||||
119
src/main/resources/templates/index.html
Normal file
119
src/main/resources/templates/index.html
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>SpaceTracker</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg1: #07111f;
|
||||
--bg2: #123a61;
|
||||
--card: #ffffff;
|
||||
--text: #0f172a;
|
||||
--muted: #334155;
|
||||
--accent: #0ea5e9;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Trebuchet MS", "Segoe UI", sans-serif;
|
||||
color: var(--text);
|
||||
background: linear-gradient(140deg, var(--bg1), var(--bg2));
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: min(900px, 100%);
|
||||
background: var(--card);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 16px 40px rgba(2, 6, 23, 0.4);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.badge {
|
||||
background: #e0f2fe;
|
||||
color: #075985;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.error {
|
||||
margin-top: 14px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 8px;
|
||||
background: #fef2f2;
|
||||
color: #991b1b;
|
||||
border: 1px solid #fecaca;
|
||||
}
|
||||
|
||||
.apod {
|
||||
margin-top: 18px;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
||||
.apod img {
|
||||
width: 100%;
|
||||
border-radius: 12px;
|
||||
margin-top: 12px;
|
||||
border: 1px solid #cbd5e1;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 0.9rem;
|
||||
color: #475569;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="card">
|
||||
<div class="top">
|
||||
<div>
|
||||
<h1>SpaceTracker</h1>
|
||||
<p>Java Spring Boot site for space missions and astronomy events.</p>
|
||||
</div>
|
||||
<span class="badge">APCSA Final</span>
|
||||
</div>
|
||||
|
||||
<div class="error" th:if="${error}" th:text="${error}">Could not load NASA APOD right now.</div>
|
||||
|
||||
<section class="apod" th:if="${apod != null}">
|
||||
<h2>NASA APOD</h2>
|
||||
<p class="small" th:text="${apod.date}">date</p>
|
||||
<h3 th:text="${apod.title}">title</h3>
|
||||
<p th:text="${apod.explanation}">explanation</p>
|
||||
<img th:if="${apod.media_type == 'image'}" th:src="${apod.url}" alt="NASA APOD image">
|
||||
<p class="small" th:if="${apod.media_type != 'image'}">
|
||||
APOD today is not an image. Open:
|
||||
<a th:href="${apod.url}" target="_blank" rel="noopener">NASA link</a>
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue