Skip to content

Commit 968b3e6

Browse files
committed
overhaul baby
1 parent af72bb2 commit 968b3e6

File tree

16 files changed

+437
-886
lines changed

16 files changed

+437
-886
lines changed

.github/workflows/azure-deploy.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Build & Deploy to Azure
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
7+
jobs:
8+
build-and-deploy:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
# 1. Grab your code
13+
- uses: actions/checkout@v3
14+
15+
# 2. Use Node 20
16+
- name: Setup Node.js
17+
uses: actions/setup-node@v3
18+
with:
19+
node-version: "20"
20+
21+
# 3. Install & build
22+
- name: Install dependencies
23+
run: npm ci
24+
- name: Build
25+
run: npm run build
26+
27+
# 4. Login to Azure via OIDC (no secret)
28+
- name: Azure Login
29+
uses: azure/login@v1
30+
with:
31+
client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_E5978DC6004B4BB995ACD60ADAF513EF }}
32+
tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_8824E98435E440FAA46E146AD7716A44 }}
33+
subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_6A3ECC57385541ACB3AC40EA396FC5B5 }}
34+
35+
# 5. Deploy to your Web App
36+
- name: Deploy to Azure Web App
37+
uses: azure/webapps-deploy@v2
38+
with:
39+
app-name: pubsite
40+
package: .

.github/workflows/main_pubsite.yml

Lines changed: 0 additions & 67 deletions
This file was deleted.

app/contact/page.js

Lines changed: 91 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,115 @@
1+
// app/contact/page.js
12
'use client'
23

34
import { useState } from 'react'
45
import Image from 'next/image'
56

6-
export default function Contact() {
7+
export default function ContactPage() {
78
const [form, setForm] = useState({ name: '', email: '', message: '' })
89
const [status, setStatus] = useState(null)
910
const [submitting, setSubmitting] = useState(false)
1011

12+
const handleChange = (e) =>
13+
setForm({ ...form, [e.target.name]: e.target.value })
14+
1115
const handleSubmit = async (e) => {
1216
e.preventDefault()
1317
setSubmitting(true)
1418
setStatus(null)
1519

16-
const res = await fetch('/api/contact', {
17-
method: 'POST',
18-
headers: { 'Content-Type': 'application/json' },
19-
body: JSON.stringify(form),
20-
})
21-
22-
if (res.ok) {
20+
try {
21+
const res = await fetch('/api/contact', {
22+
method: 'POST',
23+
headers: { 'Content-Type': 'application/json' },
24+
body: JSON.stringify(form),
25+
})
26+
if (!res.ok) throw new Error('Network response was not ok')
2327
setStatus('Message sent!')
2428
setForm({ name: '', email: '', message: '' })
25-
} else {
29+
} catch {
2630
setStatus('Failed to send message.')
31+
} finally {
32+
setSubmitting(false)
2733
}
28-
29-
setSubmitting(false)
3034
}
3135

3236
return (
33-
<div className="max-w-xl mx-auto p-8 text-center">
34-
<Image
35-
src="/portraits/casual.jpeg"
36-
width={250}
37-
height={350}
38-
className="mx-auto rounded-xl mb-6"
39-
alt="Contact Grant"
40-
/>
41-
<h2 className="text-3xl font-bold mb-4">Contact Me</h2>
42-
<form onSubmit={handleSubmit} className="space-y-4">
43-
<input
44-
required
45-
className="w-full p-2 border rounded bg-black text-white placeholder-gray-400"
46-
placeholder="Name"
47-
value={form.name}
48-
onChange={(e) => setForm({ ...form, name: e.target.value })}
49-
/>
50-
<input
51-
required
52-
type="email"
53-
className="w-full p-2 border rounded bg-black text-white placeholder-gray-400"
54-
placeholder="Email"
55-
value={form.email}
56-
onChange={(e) => setForm({ ...form, email: e.target.value })}
57-
/>
58-
<textarea
59-
required
60-
className="w-full p-2 border rounded bg-black text-white placeholder-gray-400"
61-
rows={5}
62-
placeholder="Message"
63-
value={form.message}
64-
onChange={(e) => setForm({ ...form, message: e.target.value })}
65-
/>
66-
<button
67-
type="submit"
68-
disabled={submitting}
69-
className={`w-full py-2 px-4 rounded text-white ${submitting ? 'bg-gray-500' : 'bg-blue-600 hover:bg-blue-700'}`}
70-
>
71-
{submitting ? 'Sending...' : 'Send Message'}
72-
</button>
73-
{status && <p className="text-sm mt-2">{status}</p>}
74-
</form>
37+
<div className="min-h-screen py-12">
38+
<div className="max-w-md mx-auto bg-white dark:bg-gray-700 rounded-2xl shadow-xl overflow-hidden">
39+
<div className="p-6">
40+
<div className="flex justify-center mb-6">
41+
<div className="w-32 h-32 rounded-full overflow-hidden ring-4 ring-white dark:ring-gray-800">
42+
<Image
43+
src="/portraits/casual.jpeg"
44+
alt="Contact Grant"
45+
width={128}
46+
height={128}
47+
className="object-cover"
48+
/>
49+
</div>
50+
</div>
51+
52+
<h2 className="text-2xl font-semibold text-gray-900 dark:text-gray-100 text-center mb-6">
53+
Contact Me
54+
</h2>
55+
56+
<form onSubmit={handleSubmit} className="space-y-4">
57+
<input
58+
id="name"
59+
name="name"
60+
value={form.name}
61+
onChange={handleChange}
62+
required
63+
placeholder="Your Name"
64+
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-400"
65+
/>
66+
67+
<input
68+
id="email"
69+
type="email"
70+
name="email"
71+
value={form.email}
72+
onChange={handleChange}
73+
required
74+
placeholder="Your Email"
75+
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-400"
76+
/>
77+
78+
<textarea
79+
id="message"
80+
name="message"
81+
value={form.message}
82+
onChange={handleChange}
83+
required
84+
rows={5}
85+
placeholder="Your Message"
86+
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-400"
87+
/>
88+
89+
<button
90+
type="submit"
91+
disabled={submitting}
92+
className={`w-full py-3 text-white font-medium rounded-lg transition ${
93+
submitting
94+
? 'bg-gray-400 cursor-not-allowed'
95+
: 'bg-blue-500 hover:bg-blue-600'
96+
}`}
97+
>
98+
{submitting ? 'Sending...' : 'Send Message'}
99+
</button>
100+
101+
{status && (
102+
<p
103+
className={`text-center mt-2 text-sm ${
104+
status.includes('Failed') ? 'text-red-400' : 'text-green-400'
105+
}`}
106+
>
107+
{status}
108+
</p>
109+
)}
110+
</form>
111+
</div>
112+
</div>
75113
</div>
76114
)
77115
}

app/globals.css

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,9 @@
22
@tailwind components;
33
@tailwind utilities;
44

5-
:root {
6-
--background: #ffffff;
7-
--foreground: #171717;
8-
}
9-
10-
@media (prefers-color-scheme: dark) {
11-
:root {
12-
--background: #0a0a0a;
13-
--foreground: #ededed;
14-
}
15-
}
16-
5+
/* override body colors & font */
176
body {
18-
background: var(--background);
19-
color: var(--foreground);
20-
font-family: Arial, Helvetica, sans-serif;
21-
}
7+
@apply bg-brand-light dark:bg-brand-dark
8+
text-gray-900 dark:text-gray-100
9+
font-sans;
10+
}

app/layout.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
// app/layout.js
2-
import './globals.css'
3-
import Navbar from '../components/Navbar'
4-
import Footer from '../components/Footer'
5-
import Script from 'next/script'
2+
import "./globals.css";
3+
import Navbar from "../components/Navbar";
4+
import Footer from "../components/Footer";
5+
import Script from "next/script";
66

77
export const metadata = {
8-
title: 'Grant Hawerlander',
9-
description: 'Cybersecurity, Sysadmin, Educator',
10-
}
8+
title: "Grant Hawerlander",
9+
description: "Cybersecurity, Sysadmin, Educator",
10+
};
1111

1212
export default function RootLayout({ children }) {
1313
return (
1414
<html lang="en">
1515
<head />
16-
<body className="flex flex-col min-h-screen bg-black text-white">
16+
<body className="flex flex-col min-h-screen">
1717
<Script
1818
src={`https://www.google.com/recaptcha/api.js?render=${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}`}
1919
strategy="beforeInteractive"
2020
/>
2121
<Navbar />
22-
<main className="flex-grow">{children}</main>
22+
<main className="flex-grow container mx-auto px-4 py-8">
23+
{children}
24+
</main>
2325
<Footer />
2426
</body>
2527
</html>
26-
)
28+
);
2729
}

app/page.js

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
1-
import Image from 'next/image'
1+
// app/page.js
2+
import Image from "next/image";
23

34
export default function Home() {
45
return (
5-
<div className="max-w-5xl mx-auto p-8 text-center">
6-
<Image
7-
src="/portraits/professional.jpeg"
8-
width={250}
9-
height={350}
10-
className="rounded-xl mx-auto shadow-xl"
11-
alt="Grant Hawerlander"
12-
/>
13-
<h1 className="text-4xl font-bold mt-6">Grant Hawerlander</h1>
14-
<p className="text-gray-600 mt-2">System Administrator | Cybersecurity Professional | Developer</p>
15-
<p className="mt-4 leading-relaxed text-lg">
16-
Passionate about cybersecurity, system administration, and education. Currently serving as a System Administrator at RIT Tech Management/ResNet, RTP + Socials Director at Computer Science House, and active in cybersecurity competitions and education. Currently working on mastering Cloud Security and development with Azure.
6+
<section className="mt-16 text-center mb-12">
7+
<div className="inline-block rounded-full overflow-hidden w-48 h-48 mb-4">
8+
<Image
9+
src="/portraits/professional.jpeg"
10+
alt="Grant Hawerlander"
11+
width={192}
12+
height={192}
13+
className="object-cover"
14+
/>
15+
</div>
16+
<h1 className="text-4xl font-bold">Grant Hawerlander</h1>
17+
<p className="text-xl text-gray-700 dark:text-gray-300">
18+
System Administrator | Cybersecurity Professional | Developer
1719
</p>
18-
</div>
19-
)
20+
<p className="mt-4 max-w-2xl mx-auto text-gray-600 dark:text-gray-400">
21+
Passionate about cybersecurity, system administration, and education.
22+
Currently serving as a System Administrator at RIT Tech Management/ResNet,
23+
RTP + Socials Director at Computer Science House, and active in cybersecurity
24+
competitions and education. Currently working on mastering Cloud Security
25+
and development with Azure.
26+
</p>
27+
</section>
28+
);
2029
}

0 commit comments

Comments
 (0)