aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/Http/Controllers/BookmarksController.php15
-rw-r--r--app/Http/Controllers/CalculatorsController.php13
-rw-r--r--app/Http/Controllers/ComputersController.php13
-rw-r--r--app/Http/Controllers/GuestbookController.php49
-rw-r--r--app/Http/Controllers/HomeController.php33
-rw-r--r--app/Http/Controllers/MusicController.php69
-rw-r--r--app/Http/Middleware/RateLimiter.php3
-rw-r--r--app/Models/BookmarkCategory.php36
-rw-r--r--app/Models/BookmarkSite.php35
-rw-r--r--app/Models/GuestbookEntry.php50
-rw-r--r--app/Models/User.php45
-rw-r--r--app/Providers/AppServiceProvider.php13
-rw-r--r--app/View/Components/CurrentTrack.php27
-rw-r--r--app/View/Components/DiscordStatus.php68
-rw-r--r--app/View/Components/Layout.php26
-rw-r--r--app/View/Components/Navbar.php27
-rw-r--r--app/View/Components/NeverSaid.php34
-rw-r--r--app/View/Components/TohQuote.php35
-rw-r--r--app/View/Components/TopTracks.php27
-rw-r--r--app/View/Components/Track.php29
-rw-r--r--app/View/Components/Weather.php50
21 files changed, 624 insertions, 73 deletions
diff --git a/app/Http/Controllers/BookmarksController.php b/app/Http/Controllers/BookmarksController.php
new file mode 100644
index 0000000..56aacc7
--- /dev/null
+++ b/app/Http/Controllers/BookmarksController.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\BookmarkSite;
+use App\Models\BookmarkCategory;
+use Illuminate\View\View;
+
+class BookmarksController extends Controller
+{
+ public function show() : View {
+ $categories = BookmarkCategory::with('sites')->get();
+ return view('bookmarks', compact('categories'));
+ }
+}
diff --git a/app/Http/Controllers/CalculatorsController.php b/app/Http/Controllers/CalculatorsController.php
new file mode 100644
index 0000000..38a7a41
--- /dev/null
+++ b/app/Http/Controllers/CalculatorsController.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\View\View;
+
+class CalculatorsController extends Controller
+{
+ public function show() : View {
+ return view('calculators');
+ }
+}
diff --git a/app/Http/Controllers/ComputersController.php b/app/Http/Controllers/ComputersController.php
new file mode 100644
index 0000000..e16e70d
--- /dev/null
+++ b/app/Http/Controllers/ComputersController.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\View\View;
+
+class ComputersController extends Controller
+{
+ public function show() : View {
+ return view('computers');
+ }
+}
diff --git a/app/Http/Controllers/GuestbookController.php b/app/Http/Controllers/GuestbookController.php
index 70707d7..df726ef 100644
--- a/app/Http/Controllers/GuestbookController.php
+++ b/app/Http/Controllers/GuestbookController.php
@@ -2,37 +2,46 @@
namespace App\Http\Controllers;
+use App\Models\GuestbookEntry;
use Illuminate\Http\Request;
-use DB;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Contracts\View\View;
+use Illuminate\Validation\ValidationException;
+use UAParser\Parser;
class GuestbookController extends Controller {
- public function guestbook() {
- return view('pages.guestbook');
+ public function show(): View {
+ $entries = GuestbookEntry::selectEntries();
+ $parser = Parser::create();
+
+ return view('guestbook')
+ ->with('entries', $entries)
+ ->with('parser', $parser);
}
- public function guestbookPost(Request $request) {
+ /**
+ * Creates a new guestbook entry
+ *
+ * @param Request $request
+ * @return RedirectResponse
+ * @throws ValidationException
+ */
+ public function addEntry(Request $request): RedirectResponse {
$this->validate($request, [
'name' => 'required',
'message' => 'required'
]);
- $matching_bans = DB::select('SELECT reason FROM guestbook__bans WHERE ip_address = ?', array($request->ip()));
-
- if (!empty($matching_bans)) {
- return view('errors.guestbook-ipban')->with('reason', $matching_bans[0]->reason);
- }
-
- DB::insert(
- 'INSERT INTO guestbook__entries (name, timestamp, ip_address, agent, message) values (?, ?, ?, ?, ?)',
- [
- htmlspecialchars($request->get('name')),
- time(),
- $request->ip(),
- $request->userAgent(),
- htmlspecialchars($request->get('message'))
- ]
- );
+ GuestbookEntry::insertGuestbookEntry($request);
return back()->with('success', 'Entry submitted successfully!');
}
+
+ public function banIP(string $addr) {
+ // TODO: Add banning system
+ // $matching_bans = DB::select('SELECT reason FROM guestbook__bans WHERE ip_address = ?', array($request->ip()));
+ // if (!empty($matching_bans)) {
+ // return view('errors.guestbook-ipban')->with('reason', $matching_bans[0]->reason);
+ // }
+ }
}
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
new file mode 100644
index 0000000..e046d58
--- /dev/null
+++ b/app/Http/Controllers/HomeController.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Http;
+use Illuminate\View\View;
+use DateTime;
+
+class HomeController extends Controller {
+ /**
+ * Returns age based on birthday date and current date (GMT)
+ * @return int
+ */
+ function returnAge(): int {
+ date_default_timezone_set('Europe/London');
+ $birthday = new DateTime("2005-06-07");
+ $currentDate = DateTime::createFromFormat("Y-m-d", date("Y-m-d"));
+ $age = $birthday->diff($currentDate);
+ return $age->y;
+ }
+
+ /**
+ * Shows home page
+ * @return View
+ */
+ public function show(): View {
+ return view('home', [
+ 'age' => $this->returnAge(),
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/MusicController.php b/app/Http/Controllers/MusicController.php
new file mode 100644
index 0000000..5e31d86
--- /dev/null
+++ b/app/Http/Controllers/MusicController.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Http;
+use Illuminate\View\View;
+
+class MusicController extends Controller
+{
+ public function getCurrentTrack() {
+ // If it's already cached just return that
+ if (Cache::has('current_track')) {
+ return Cache::get('current_track');
+ }
+
+ $response = Http::withQueryParameters([
+ 'method' => 'user.getrecenttracks',
+ 'user' => Config::get('services.lastfm.user'),
+ 'format' => 'json',
+ 'nowplaying' => 'true',
+ 'api_key' => Config::get('services.lastfm.key')
+ ])->get('https://ws.audioscrobbler.com/2.0/');
+ $data = $response->json();
+ error_log($response->body());
+ $track_data = $data["recenttracks"]["track"][0];
+ $current_track = [
+ 'title' => $track_data["name"],
+ 'artist' => $track_data["artist"]["#text"],
+ 'url' => $track_data["url"],
+ ];
+ Cache::put('current_track', $current_track, now()->addSeconds(15));
+ return $current_track;
+ }
+
+ public function getTopTracks() {
+ // If it's already cached just return that
+ if (Cache::has('top_tracks')) {
+ return Cache::get('top_tracks');
+ }
+
+ $response = Http::withQueryParameters([
+ 'method' => 'user.gettoptracks',
+ 'user' => Config::get('services.lastfm.user'),
+ 'format' => 'json',
+ 'period' => '1month',
+ 'limit' => 10,
+ 'api_key' => Config::get('services.lastfm.key')
+ ])->get('https://ws.audioscrobbler.com/2.0/');
+ $data = $response->json();
+ $topTracks = [];
+ foreach ($data["toptracks"]["track"] as $track) {
+ $topTracks[] = [
+ 'title' => $track["name"],
+ 'artist' => $track["artist"]["name"],
+ 'url' => $track["url"],
+ 'plays' => $track["playcount"],
+ ];
+ }
+ Cache::put('top_tracks', $topTracks, now()->addSeconds(15));
+ return $topTracks;
+ }
+ public function show() : View {
+ return view('music')
+ ->with('current_track', $this->getCurrentTrack())
+ ->with('top_tracks', $this->getTopTracks());
+ }
+}
diff --git a/app/Http/Middleware/RateLimiter.php b/app/Http/Middleware/RateLimiter.php
index 09eb0a9..821868f 100644
--- a/app/Http/Middleware/RateLimiter.php
+++ b/app/Http/Middleware/RateLimiter.php
@@ -16,6 +16,9 @@ class RateLimiter
*/
public function handle(Request $request, Closure $next): Response
{
+ if (auth()->check()) {
+ return $next($request);
+ }
$ipAddress = $request->ip();
$cacheKey = 'rate_limit_'.$ipAddress;
diff --git a/app/Models/BookmarkCategory.php b/app/Models/BookmarkCategory.php
new file mode 100644
index 0000000..a8bc8d2
--- /dev/null
+++ b/app/Models/BookmarkCategory.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class BookmarkCategory extends Model
+{
+ use HasFactory;
+ protected $table = "bookmark__categories";
+ protected $fillable = ['name'];
+
+ public function sites() {
+ return $this->hasMany(BookmarkSite::class, 'category');
+ }
+
+ public static function insertBookmarkCategory(string $name) {
+ $newBookmarkCategory = new BookmarkCategory;
+ $newBookmarkCategory->name = $name;
+ $newBookmarkCategory->save();
+ }
+ public static function selectBookmarks(int $id) {
+ $bookmarks = BookmarkSite::where('category', '=', $id)->firstOrFail();
+ return $bookmarks;
+ }
+
+ public static function importBookmarkCategory(array $data) {
+ foreach ($data as $category) {
+ $newBookmarkCategory = new BookmarkCategory;
+ $newBookmarkCategory->name = $category['name'];
+ $newBookmarkCategory->priority = intval($category['priority']);
+ $newBookmarkCategory->save();
+ }
+ }
+}
diff --git a/app/Models/BookmarkSite.php b/app/Models/BookmarkSite.php
new file mode 100644
index 0000000..3c9cc5d
--- /dev/null
+++ b/app/Models/BookmarkSite.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class BookmarkSite extends Model {
+ use HasFactory;
+ protected $table = "bookmark__sites";
+ protected $fillable = ['name', 'description', 'url', 'category'];
+
+ public function category() {
+ return $this->belongsTo(BookmarkCategory::class, 'category');
+ }
+ public static function insertBookmark(string $name, string $url, int $category) {
+ $category = BookmarkCategory::where('id', $category)->firstOrFail();
+ $newBookmark = new BookmarkSite;
+ $newBookmark->name = $name;
+ $newBookmark->url = $url;
+ $newBookmark->category = $category->id;
+ $newBookmark->save();
+ }
+
+ public static function importBookmark(array $data) {
+ foreach ($data as $site) {
+ $newBookmark = new BookmarkSite;
+ $newBookmark->name = $site['name'];
+ $newBookmark->description = $site['description'];
+ $newBookmark->url = $site['url'];
+ $newBookmark->category = $site['category_id'];
+ $newBookmark->save();
+ }
+ }
+}
diff --git a/app/Models/GuestbookEntry.php b/app/Models/GuestbookEntry.php
new file mode 100644
index 0000000..f5e2de2
--- /dev/null
+++ b/app/Models/GuestbookEntry.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Http\Request;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class GuestbookEntry extends Model
+{
+ use HasFactory;
+ protected $table = "guestbook__entries";
+ protected $fillable = ['name', 'message'];
+
+ /**
+ * Creates a new guestbook entry.
+ *
+ * @param Request $request The HTTP POST request
+ * @return void
+ */
+ public static function insertGuestbookEntry(Request $request) {
+ $newEntry = new GuestbookEntry;
+ $newEntry->name = htmlspecialchars($request->get('name'));
+ $newEntry->message = htmlspecialchars($request->get('message'));
+ $newEntry->ip = $request->ip();
+ $newEntry->agent = $request->userAgent();
+ $newEntry->admin = auth()->check();
+ $newEntry->save();
+ }
+
+ public static function selectEntries() {
+ $entries = GuestbookEntry::orderBy('created_at', 'desc')->get();
+ return $entries;
+ }
+
+ public static function importGuestbookEntry(array $data) {
+ foreach ($data as $entry) {
+ $dt = new \DateTime('@' . $entry['timestamp']);
+ $newEntry = new GuestbookEntry;
+ $newEntry->name = $entry['name'];
+ $newEntry->ip = $entry['ip_address'];
+ $newEntry->agent = $entry['agent'];
+ $newEntry->admin = $entry['site_owner'];
+ $newEntry->message = $entry['message'];
+ $newEntry->created_at = $dt;
+ $newEntry->updated_at = $dt;
+ $newEntry->save();
+ }
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
deleted file mode 100644
index 4d7f70f..0000000
--- a/app/Models/User.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-namespace App\Models;
-
-// use Illuminate\Contracts\Auth\MustVerifyEmail;
-use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Foundation\Auth\User as Authenticatable;
-use Illuminate\Notifications\Notifiable;
-use Laravel\Sanctum\HasApiTokens;
-
-class User extends Authenticatable
-{
- use HasApiTokens, HasFactory, Notifiable;
-
- /**
- * The attributes that are mass assignable.
- *
- * @var array<int, string>
- */
- protected $fillable = [
- 'name',
- 'email',
- 'password',
- ];
-
- /**
- * The attributes that should be hidden for serialization.
- *
- * @var array<int, string>
- */
- protected $hidden = [
- 'password',
- 'remember_token',
- ];
-
- /**
- * The attributes that should be cast.
- *
- * @var array<string, string>
- */
- protected $casts = [
- 'email_verified_at' => 'datetime',
- 'password' => 'hashed',
- ];
-}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 452e6b6..2209133 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -2,23 +2,20 @@
namespace App\Providers;
+use Illuminate\Support\Facades\Config;
use Illuminate\Support\ServiceProvider;
+use PostHog\PostHog;
-class AppServiceProvider extends ServiceProvider
-{
+class AppServiceProvider extends ServiceProvider {
/**
* Register any application services.
*/
- public function register(): void
- {
+ public function register(): void {
//
}
/**
* Bootstrap any application services.
*/
- public function boot(): void
- {
- //
- }
+ public function boot(): void {}
}
diff --git a/app/View/Components/CurrentTrack.php b/app/View/Components/CurrentTrack.php
new file mode 100644
index 0000000..337809a
--- /dev/null
+++ b/app/View/Components/CurrentTrack.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class CurrentTrack extends Component
+{
+ public $track;
+ /**
+ * Create a new component instance.
+ */
+ public function __construct($track)
+ {
+ $this->track = $track;
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.current-track');
+ }
+}
diff --git a/app/View/Components/DiscordStatus.php b/app/View/Components/DiscordStatus.php
new file mode 100644
index 0000000..3ad3a3b
--- /dev/null
+++ b/app/View/Components/DiscordStatus.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Http;
+use Illuminate\View\Component;
+
+class DiscordStatus extends Component
+{
+ /**
+ * Create a new component instance.
+ */
+ public function __construct()
+ {
+ //
+ }
+
+ /**
+ * Returns current Discord presence from Lanyard API
+ * @return array|mixed
+ */
+ public function getDiscordPresence(): mixed {
+ // If it's already cached just return that
+ if (Cache::has('discord_presence')) {
+ return Cache::get('discord_presence');
+ }
+
+ $response = Http::get('https://api.lanyard.rest/v1/users/' . Config::get('services.lanyard.user_id'));
+ $data = $response->json();
+ if (!isset($data["data"])) return null;
+ $presence = $data["data"];
+ Cache::put('discord_presence', $presence, now()->addSeconds(60));
+ return $presence;
+ }
+
+ public function getOnlineStatus(): ?array {
+ $presence = $this->getDiscordPresence();
+ if ($presence == null) return null;
+ return match ($presence["discord_status"]) {
+ "online", "dnd" => [
+ "text" => "online",
+ "color" => "#02c83a"
+ ],
+ "idle" => [
+ "text" => "away",
+ "color" => "#d77c20"
+ ],
+ default => [
+ "text" => "offline",
+ "color" => "#ca3329"
+ ],
+ };
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.discord-status', [
+ 'status' => $this->getOnlineStatus(),
+ ]);
+ }
+}
diff --git a/app/View/Components/Layout.php b/app/View/Components/Layout.php
new file mode 100644
index 0000000..576d1a0
--- /dev/null
+++ b/app/View/Components/Layout.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Layout extends Component
+{
+ /**
+ * Create a new component instance.
+ */
+ public function __construct()
+ {
+ //
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.layout');
+ }
+}
diff --git a/app/View/Components/Navbar.php b/app/View/Components/Navbar.php
new file mode 100644
index 0000000..7f119fe
--- /dev/null
+++ b/app/View/Components/Navbar.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Navbar extends Component
+{
+ public $title;
+ /**
+ * Create a new component instance.
+ */
+ public function __construct($title)
+ {
+ $this->title = $title;
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.navigation');
+ }
+}
diff --git a/app/View/Components/NeverSaid.php b/app/View/Components/NeverSaid.php
new file mode 100644
index 0000000..c9e1006
--- /dev/null
+++ b/app/View/Components/NeverSaid.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class NeverSaid extends Component
+{
+ /**
+ * Create a new component instance.
+ */
+ public function __construct()
+ {
+ //
+ }
+
+ function returnQuote(): array {
+ $quotes = config('quotes.neversaid');
+ $index = rand(0, count($quotes) - 1);
+ return $quotes[$index];
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.never-said', [
+ "quote" => $this->returnQuote()
+ ]);
+ }
+}
diff --git a/app/View/Components/TohQuote.php b/app/View/Components/TohQuote.php
new file mode 100644
index 0000000..a53d713
--- /dev/null
+++ b/app/View/Components/TohQuote.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class TohQuote extends Component
+{
+ /**
+ * Create a new component instance.
+ */
+ public function __construct()
+ {
+ //
+ }
+
+ function returnQuote(): array {
+ $quotes = config('quotes.toh');
+ $index = rand(0, count($quotes) - 1);
+ return $quotes[$index];
+ }
+
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.toh-quote',[
+ 'quote' => $this->returnQuote()
+ ]);
+ }
+}
diff --git a/app/View/Components/TopTracks.php b/app/View/Components/TopTracks.php
new file mode 100644
index 0000000..768ce33
--- /dev/null
+++ b/app/View/Components/TopTracks.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class TopTracks extends Component
+{
+ public $tracks;
+ /**
+ * Create a new component instance.
+ */
+ public function __construct($tracks)
+ {
+ $this->tracks = $tracks;
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.top-tracks');
+ }
+}
diff --git a/app/View/Components/Track.php b/app/View/Components/Track.php
new file mode 100644
index 0000000..b9f628f
--- /dev/null
+++ b/app/View/Components/Track.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Illuminate\Contracts\View\View;
+use Illuminate\View\Component;
+
+class Track extends Component
+{
+ public $track;
+ public $count;
+ /**
+ * Create a new component instance.
+ */
+ public function __construct($track, $count)
+ {
+ $this->track = $track;
+ $this->count = $count;
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.track');
+ }
+}
diff --git a/app/View/Components/Weather.php b/app/View/Components/Weather.php
new file mode 100644
index 0000000..dcf3ff7
--- /dev/null
+++ b/app/View/Components/Weather.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace App\View\Components;
+
+use Closure;
+use Exception;
+use Illuminate\Contracts\View\View;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Http;
+use Illuminate\View\Component;
+
+class Weather extends Component
+{
+ /**
+ * Create a new component instance.
+ */
+ public function __construct()
+ {
+ //
+ }
+
+ public function getWeatherData(): mixed {
+ // If it's already cached just return that
+ if (Cache::has('weather_data')) {
+ return Cache::get('weather_data');
+ }
+
+ try {
+ $response = Http::get('http://' . Config::get('services.weatherlink') . '/v1/current_conditions');
+ $data = $response->json();
+ $conditions = $data["data"]["conditions"];
+ Cache::put('weather_data', $conditions, now()->addSeconds(60));
+ return $conditions;
+ } catch (Exception $ex) {
+ return null;
+ }
+
+ }
+
+ /**
+ * Get the view / contents that represent the component.
+ */
+ public function render(): View|Closure|string
+ {
+ return view('components.weather', [
+ 'conditions' => $this->getWeatherData(),
+ ]);
+ }
+}