QoL update

This commit is contained in:
Ben Mosley
2026-04-22 22:09:08 -05:00
parent 4d091a15cd
commit 7c9b904985
15 changed files with 449 additions and 291 deletions

Binary file not shown.

View File

@@ -32,11 +32,21 @@
<tbody>
{% for projectpost in projectpost %}
<tr class="border-b border-[rgb(var(--border))] hover:bg-[rgb(var(--card))]/60 transition">
<td class="px-5 py-3 text-[rgb(var(--fg))] font-medium">{{ projectpost.title }}</td>
<td class="px-5 py-3 text-[rgb(var(--fg))] font-medium">
{{ projectpost.title }}
{% if projectpost.draft %}
<span class="ml-2 text-xs font-semibold bg-yellow-500/20 text-yellow-300 border border-yellow-400/40 px-2 py-0.5 rounded-full">Draft</span>
{% endif %}
</td>
<td class="px-5 py-3 text-[rgb(var(--muted))]">{{ projectpost.category }}</td>
<td class="px-5 py-3 flex flex-wrap gap-2">
<a href="{{ url_for('view_project', slug=projectpost.slug) }}" class="btn btn-ghost border-none bg-blue-600 hover:bg-blue-700 text-white">View</a>
<a href="{{ url_for('view_project', slug=projectpost.slug) }}" class="btn btn-ghost border-none bg-blue-600 hover:bg-blue-700 text-white">Preview</a>
<a href="{{ url_for('edit_project', slug=projectpost.slug) }}" class="btn btn-ghost border-none bg-yellow-500 hover:bg-yellow-600 text-white">Edit</a>
{% if projectpost.draft %}
<form action="{{ url_for('publish_project', slug=projectpost.slug) }}" method="POST">
<button type="submit" class="btn btn-ghost border-none bg-green-600 hover:bg-green-700 text-white">Publish</button>
</form>
{% endif %}
<form action="{{ url_for('delete_project', slug=projectpost.slug) }}" method="POST" onsubmit="return confirm('Delete this project?');">
<button type="submit" class="btn btn-ghost border-none bg-red-600 hover:bg-red-700 text-white">Delete</button>
</form>
@@ -74,11 +84,21 @@
<tbody>
{% for blogpost in blogpost %}
<tr class="border-b border-[rgb(var(--border))] hover:bg-[rgb(var(--card))]/60 transition">
<td class="px-5 py-3 text-[rgb(var(--fg))] font-medium">{{ blogpost.title }}</td>
<td class="px-5 py-3 text-[rgb(var(--fg))] font-medium">
{{ blogpost.title }}
{% if blogpost.draft %}
<span class="ml-2 text-xs font-semibold bg-yellow-500/20 text-yellow-300 border border-yellow-400/40 px-2 py-0.5 rounded-full">Draft</span>
{% endif %}
</td>
<td class="px-5 py-3 text-[rgb(var(--muted))]">{{ blogpost.category }}</td>
<td class="px-5 py-3 flex flex-wrap gap-2">
<a href="{{ url_for('view_blog', slug=blogpost.slug) }}" class="btn btn-ghost border-none bg-blue-600 hover:bg-blue-700 text-white">View</a>
<a href="{{ url_for('view_blog', slug=blogpost.slug) }}" class="btn btn-ghost border-none bg-blue-600 hover:bg-blue-700 text-white">Preview</a>
<a href="{{ url_for('edit_blog', slug=blogpost.slug) }}" class="btn btn-ghost border-none bg-yellow-500 hover:bg-yellow-600 text-white">Edit</a>
{% if blogpost.draft %}
<form action="{{ url_for('publish_blog', slug=blogpost.slug) }}" method="POST">
<button type="submit" class="btn btn-ghost border-none bg-green-600 hover:bg-green-700 text-white">Publish</button>
</form>
{% endif %}
<form action="{{ url_for('delete_blog', slug=blogpost.slug) }}" method="POST" onsubmit="return confirm('Delete this post?');">
<button type="submit" class="btn btn-ghost border-none bg-red-600 hover:bg-red-700 text-white">Delete</button>
</form>

View File

@@ -1,29 +1,111 @@
{% extends "base.html" %}
{% block title %}Edit Blog{% endblock %}
{% block title %}Edit — {{ blogpost.title }}{% endblock %}
{% block head %}
<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">
{% endblock %}
{% block content %}
<form method="POST" enctype="multipart/form-data">
<label>Title:</label>
<input type="text" name="title" value="{{ blogpost.title }}" required>
<!-- Hero -->
<section class="py-20 bg-gradient-to-br from-red-800 to-orange-400 text-white text-center">
<h1 class="text-5xl font-extrabold mb-2">Edit Blog Post</h1>
<p class="text-lg opacity-90">{{ blogpost.title }}</p>
</section>
<label>Content:</label>
<textarea name="content">{{ blogpost.content|replace('<br>', '\n') }}</textarea>
<!-- Form -->
<section class="py-16 bg-black text-white">
<div class="max-w-3xl mx-auto px-6">
<form method="POST" enctype="multipart/form-data" class="space-y-6">
<label>Category:</label>
<input type="text" name="category" value="{{ blogpost.category }}">
<!-- Title -->
<div>
<label for="title" class="block font-semibold mb-1">Post Title</label>
<input type="text" id="title" name="title" value="{{ blogpost.title }}" required
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<label>Tags:</label>
<input type="text" name="tags" value="{{ blogpost.tags }}">
<!-- Content -->
<div>
<label for="content" class="block font-semibold mb-1">Post Content</label>
<textarea id="content" name="content" required
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 leading-relaxed text-base focus:ring-2 focus:ring-orange-400 focus:outline-none resize-none overflow-hidden"
rows="1">{{ blogpost.content|replace('<br>', '\n') }}</textarea>
</div>
<!-- Category -->
<div>
<label for="category" class="block font-semibold mb-1">Category</label>
<input type="text" id="category" name="category" value="{{ blogpost.category or '' }}"
placeholder="What's This Post About?"
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<label>Upload New Images:</label>
<input type="file" name="images" multiple>
<!-- Tags -->
<div>
<label for="tags" class="block font-semibold mb-1">Tags (comma-separated)</label>
<input type="text" id="tags" name="tags" value="{{ blogpost.tags or '' }}"
placeholder="e.g., Flask, SQLite, API"
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<button type="submit">Save Changes</button>
</form>
<!-- Pinned -->
<div class="flex items-center gap-2">
<input type="checkbox" id="pinned" name="pinned" {% if blogpost.pinned %}checked{% endif %}
class="w-4 h-4 accent-orange-500">
<label for="pinned" class="font-semibold">Pin this post</label>
</div>
<!-- Existing Images -->
{% if blogpost.images %}
{% set imgs = blogpost.images|from_json %}
{% if imgs %}
<div>
<p class="font-semibold mb-2">Current Images</p>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-3">
{% for img in imgs %}
<div class="overflow-hidden rounded-lg border border-gray-700">
<img src="{{ url_for('static', filename='uploads/' + img) }}"
alt="{{ img }}" class="w-full h-32 object-cover">
<p class="text-xs text-gray-400 truncate px-2 py-1">{{ img }}</p>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endif %}
<!-- Upload New Images -->
<div>
<label for="images" class="block font-semibold mb-1">Upload New Images</label>
<input type="file" name="images" id="images" multiple
class="text-black w-full border border-gray-300 rounded px-3 py-2 text-gray-700 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:bg-orange-600 file:text-white hover:file:bg-orange-700">
<p class="text-xs text-gray-400 mt-1">New images are added alongside existing ones.</p>
</div>
<!-- Actions -->
<div class="pt-4 flex flex-wrap gap-3">
<button type="submit"
class="bg-orange-600 text-white px-6 py-2 rounded hover:bg-orange-700 transition">
Save Changes
</button>
<a href="{{ url_for('view_blog', slug=blogpost.slug) }}"
class="bg-gray-700 text-white px-6 py-2 rounded hover:bg-gray-600 transition">
Cancel
</a>
</div>
</form>
</div>
</section>
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
<script>
new EasyMDE({
element: document.getElementById('content'),
spellChecker: false,
toolbar: ['bold','italic','heading','|','quote','unordered-list','ordered-list','|','link','image','|','preview','side-by-side','fullscreen','|','guide'],
});
</script>
{% endblock %}

View File

@@ -1,26 +1,111 @@
{% extends "base.html" %}
{% block title %}Edit Project{% endblock %}
{% block title %}Edit — {{ projectpost.title }}{% endblock %}
{% block head %}
<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">
{% endblock %}
{% block content %}
<form method="POST" enctype="multipart/form-data">
<label>Title:</label>
<input type="text" name="title" value="{{ projectpost.title }}" required>
<label>Content:</label>
<textarea name="content">{{ projectpost.content|replace('<br>', '\n') }}</textarea>
<!-- Hero -->
<section class="py-20 bg-gradient-to-br from-red-800 to-orange-400 text-white text-center">
<h1 class="text-5xl font-extrabold mb-2">Edit Project Post</h1>
<p class="text-lg opacity-90">{{ projectpost.title }}</p>
</section>
<label>Category:</label>
<input type="text" name="category" value="{{ projectpost.category }}">
<!-- Form -->
<section class="py-16 bg-black text-white">
<div class="max-w-3xl mx-auto px-6">
<form method="POST" enctype="multipart/form-data" class="space-y-6">
<label>Tags:</label>
<input type="text" name="tags" value="{{ projectpost.tags }}">
<!-- Title -->
<div>
<label for="title" class="block font-semibold mb-1">Post Title</label>
<input type="text" id="title" name="title" value="{{ projectpost.title }}" required
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<!-- Content -->
<div>
<label for="content" class="block font-semibold mb-1">Post Content</label>
<textarea id="content" name="content" required
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 leading-relaxed text-base focus:ring-2 focus:ring-orange-400 focus:outline-none resize-none overflow-hidden"
rows="1">{{ projectpost.content|replace('<br>', '\n') }}</textarea>
</div>
<label>Upload New Images:</label>
<input type="file" name="images" multiple>
<!-- Category -->
<div>
<label for="category" class="block font-semibold mb-1">Category</label>
<input type="text" id="category" name="category" value="{{ projectpost.category or '' }}"
placeholder="What's This Post About?"
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<button type="submit">Save Changes</button>
</form>
<!-- Tags -->
<div>
<label for="tags" class="block font-semibold mb-1">Tags (comma-separated)</label>
<input type="text" id="tags" name="tags" value="{{ projectpost.tags or '' }}"
placeholder="e.g., Flask, SQLite, API"
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<!-- Pinned -->
<div class="flex items-center gap-2">
<input type="checkbox" id="pinned" name="pinned" {% if projectpost.pinned %}checked{% endif %}
class="w-4 h-4 accent-orange-500">
<label for="pinned" class="font-semibold">Pin this post</label>
</div>
<!-- Existing Images -->
{% if projectpost.images %}
{% set imgs = projectpost.images|from_json %}
{% if imgs %}
<div>
<p class="font-semibold mb-2">Current Images</p>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-3">
{% for img in imgs %}
<div class="overflow-hidden rounded-lg border border-gray-700">
<img src="{{ url_for('static', filename='uploads/' + img) }}"
alt="{{ img }}" class="w-full h-32 object-cover">
<p class="text-xs text-gray-400 truncate px-2 py-1">{{ img }}</p>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endif %}
<!-- Upload New Images -->
<div>
<label for="images" class="block font-semibold mb-1">Upload New Images</label>
<input type="file" name="images" id="images" multiple
class="text-black w-full border border-gray-300 rounded px-3 py-2 text-gray-700 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:bg-orange-600 file:text-white hover:file:bg-orange-700">
<p class="text-xs text-gray-400 mt-1">New images are added alongside existing ones.</p>
</div>
<!-- Actions -->
<div class="pt-4 flex flex-wrap gap-3">
<button type="submit"
class="bg-orange-600 text-white px-6 py-2 rounded hover:bg-orange-700 transition">
Save Changes
</button>
<a href="{{ url_for('view_project', slug=projectpost.slug) }}"
class="bg-gray-700 text-white px-6 py-2 rounded hover:bg-gray-600 transition">
Cancel
</a>
</div>
</form>
</div>
</section>
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
<script>
new EasyMDE({
element: document.getElementById('content'),
spellChecker: false,
toolbar: ['bold','italic','heading','|','quote','unordered-list','ordered-list','|','link','image','|','preview','side-by-side','fullscreen','|','guide'],
});
</script>
{% endblock %}

View File

@@ -24,7 +24,7 @@
</div>
<div class="justify-self-center">
<img src="{{ url_for('static', filename='Headshot.jpg') }}"
<img src="{{ url_for('static', filename='Headshot.jpeg') }}"
alt="Portrait of Benjamin Mosley"
class="h-40 w-40 sm:h-52 sm:w-52 rounded-2xl border border-[rgb(var(--border))] shadow-glass object-cover">
</div>

View File

@@ -2,6 +2,10 @@
{% block title %}New Blog Post{% endblock %}
{% block head %}
<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">
{% endblock %}
{% block content %}
<!-- Hero -->
@@ -12,21 +16,21 @@
<!-- Form -->
<section class="py-16 bg-black text-white">
<div class="max-w-3xl mx-auto px-6 max-h-[85vh] overflow-y-auto">
<div class="max-w-3xl mx-auto px-6">
<form action="{{ url_for('new_blog') }}" method="post" enctype="multipart/form-data" class="space-y-6">
<!-- Title -->
<div>
<label for="title" class="block font-semibold mb-1">Post Title</label>
<input type="text" id="title" name="title" required
class="text-black w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<!-- Content -->
<div>
<label for="content" class="block font-semibold mb-1">Post Content</label>
<textarea id="content" name="content" required
class="text-black w-full border border-gray-300 rounded px-4 py-2 leading-relaxed text-base focus:ring-2 focus:ring-orange-400 focus:outline-none resize-none overflow-hidden"
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 leading-relaxed text-base focus:ring-2 focus:ring-orange-400 focus:outline-none resize-none overflow-hidden"
rows="1"></textarea>
</div>
@@ -34,14 +38,14 @@
<div>
<label for="category" class="block font-semibold mb-1">Category</label>
<input type="text" id="category" name="category" placeholder="What's This Post About?"
class="text-black w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<!-- Tags -->
<div>
<label for="tags" class="block font-semibold mb-1">Tags (comma-separated)</label>
<input type="text" id="tags" name="tags" placeholder="e.g., Flask, SQLite, API"
class="text-black w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
class="text-black bg-white w-full border border-gray-300 rounded px-4 py-2 focus:ring-2 focus:ring-orange-400 focus:outline-none">
</div>
<!-- Images -->
@@ -52,10 +56,14 @@
</div>
<!-- Submit -->
<div class="pt-4">
<button type="submit"
<div class="pt-4 flex gap-3">
<button type="submit" name="action" value="draft"
class="bg-gray-600 text-white px-6 py-2 rounded hover:bg-gray-500 transition">
Save as Draft
</button>
<button type="submit" name="action" value="publish"
class="bg-orange-600 text-white px-6 py-2 rounded hover:bg-orange-700 transition">
Submit Post
Publish Post
</button>
</div>
</form>
@@ -67,18 +75,13 @@
</div>
</section>
<!-- Textarea autoresize -->
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const textarea = document.getElementById('content');
if (textarea) {
const resize = () => {
textarea.style.height = 'auto';
textarea.style.height = textarea.scrollHeight + 'px';
};
resize(); // Initial sizing
textarea.addEventListener('input', resize);
}
new EasyMDE({
element: document.getElementById('content'),
spellChecker: false,
autosave: { enabled: true, uniqueId: 'new_blog' },
toolbar: ['bold','italic','heading','|','quote','unordered-list','ordered-list','|','link','image','|','preview','side-by-side','fullscreen','|','guide'],
});
</script>

View File

@@ -2,6 +2,10 @@
{% block title %}New Project Post{% endblock %}
{% block head %}
<link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">
{% endblock %}
{% block content %}
<!-- Hero Section -->
@@ -12,7 +16,7 @@
<!-- Form Section -->
<section class="py-16 bg-black text-white">
<div class="max-w-3xl mx-auto px-6 max-h-[85vh] overflow-y-auto">
<div class="max-w-3xl mx-auto px-6">
<form action="{{ url_for('new_project') }}" method="post" enctype="multipart/form-data" class="space-y-6">
<!-- Title -->
@@ -52,10 +56,14 @@
</div>
<!-- Submit -->
<div class="pt-4">
<button type="submit"
<div class="pt-4 flex gap-3">
<button type="submit" name="action" value="draft"
class="bg-gray-600 text-white px-6 py-2 rounded hover:bg-gray-500 transition">
Save as Draft
</button>
<button type="submit" name="action" value="publish"
class="bg-orange-600 text-white px-6 py-2 rounded hover:bg-orange-700 transition">
Submit Post
Publish Post
</button>
</div>
</form>
@@ -66,18 +74,13 @@
</div>
</section>
<!-- Textarea Auto-Expand Script -->
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const textarea = document.getElementById('content');
if (textarea) {
const resize = () => {
textarea.style.height = 'auto';
textarea.style.height = textarea.scrollHeight + 'px';
};
resize(); // Set initial height
textarea.addEventListener('input', resize);
}
new EasyMDE({
element: document.getElementById('content'),
spellChecker: false,
autosave: { enabled: true, uniqueId: 'new_project' },
toolbar: ['bold','italic','heading','|','quote','unordered-list','ordered-list','|','link','image','|','preview','side-by-side','fullscreen','|','guide'],
});
</script>

View File

@@ -7,31 +7,30 @@
<section class="relative text-center py-24 text-white bg-gradient-to-br from-orange-500/20 via-rose-500/10 to-fuchsia-500/10 backdrop-blur border-b border-white/10">
<div class="max-w-3xl mx-auto px-6">
<h1 class="text-5xl md:text-6xl font-archivo font-extrabold">Benjamin Mosley</h1>
<p class="mt-3 text-white/80 text-lg">E-Commerce Manager - CIS Student</p>
<p class="mt-3 text-white/80 text-lg">IT Support · Network &amp; Systems · CIS Student</p>
<div class="mt-6 flex flex-wrap items-center justify-center gap-3 text-sm">
<span class="px-3 py-1 rounded-full border border-white/15 bg-white/5">Canyon, TX 79015</span>
<span class="px-3 py-1 rounded-full border border-white/15 bg-white/5">Amarillo, TX 79119</span>
<a href="mailto:benjaymos@proton.me" class="px-3 py-1 rounded-full border border-white/15 bg-white/5 hover:bg-white/10 transition">benjaymos@proton.me</a>
<a href="https://benjaminmosley.com" target="_blank" class="px-3 py-1 rounded-full border border-white/15 bg-white/5 hover:bg-white/10 transition">benjaminmosley.com</a>
{# Optional: add a real static path if you place the PDF under /static/ #}
{# <a href="{{ url_for('static', filename='Benjamin Mosley - Resume.pdf') }}" class="btn btn-ghost">Download PDF</a> #}
</div>
</div>
</section>
<!-- About -->
<section class="py-14">
<!-- Leadership & Awards -->
<section class="py-10">
<div class="container-page">
<article class="card max-w-4xl mx-auto">
<h2 class="text-2xl font-semibold">About Me</h2>
<p class="mt-3 text-white/80 leading-relaxed">
Ive been working with computers for as long as I can remember—what started as curiosity has grown into a passion.
From backend scripting and networking to frontend design, I enjoy creating efficient and user-friendly solutions.
</p>
<h2 class="text-2xl font-semibold">Leadership &amp; Awards</h2>
<ul class="mt-3 text-white/80 space-y-2 list-disc pl-5">
<li>Carey Lyles Emerging Technology Award — West Texas A&amp;M University (2026)</li>
<li>Eagle Scout (Dec 2021)</li>
<li>National Youth Leadership Training (20172019)</li>
</ul>
</article>
</div>
</section>
<!-- Skills & Education (balanced two-column layout) -->
<!-- Skills & Education -->
<section class="py-6">
<div class="container-page grid md:grid-cols-2 gap-6 items-stretch">
<!-- Skills -->
@@ -40,40 +39,52 @@
<div class="mt-4 grid sm:grid-cols-2 gap-6 text-sm">
<div>
<p class="font-medium text-white/90">Programming</p>
<p class="font-medium text-white/90">Endpoint &amp; Systems</p>
<ul class="mt-2 space-y-1 text-white/70 list-disc pl-5">
<li>PC imaging &amp; deployment</li>
<li>Windows Server / AD</li>
<li>Microsoft 365 / Entra ID</li>
<li>Endpoint patching</li>
<li>Asset tracking</li>
</ul>
</div>
<div>
<p class="font-medium text-white/90">Networking</p>
<ul class="mt-2 space-y-1 text-white/70 list-disc pl-5">
<li>Switch &amp; AP config</li>
<li>Firewall rules</li>
<li>Fixed wireless (Cambium)</li>
<li>Fiber / Adtran</li>
<li>TCP/IP, DNS, DHCP</li>
</ul>
</div>
<div>
<p class="font-medium text-white/90">Scripting &amp; Dev</p>
<ul class="mt-2 space-y-1 text-white/70 list-disc pl-5">
<li>PowerShell / Bash</li>
<li>Python</li>
<li>C#, ASP.NET Core</li>
</ul>
</div>
<div>
<p class="font-medium text-white/90">Web &amp; Database</p>
<ul class="mt-2 space-y-1 text-white/70 list-disc pl-5">
<li>Flask, Tailwind CSS</li>
<li>SQL (MySQL, SQLite), EF Core</li>
</ul>
</div>
<div>
<p class="font-medium text-white/90">Systems</p>
<ul class="mt-2 space-y-1 text-white/70 list-disc pl-5">
<li>Linux, Windows Server</li>
<li>Networking &amp; Security</li>
<li>C# / ASP.NET</li>
<li>Flask / SQL</li>
<li>Git / GitHub</li>
</ul>
</div>
<div>
<p class="font-medium text-white/90">Professional</p>
<ul class="mt-2 space-y-1 text-white/70 list-disc pl-5">
<li>Leadership &amp; Team Ops</li>
<li>Process Improvement</li>
<li>Ticketing &amp; documentation</li>
<li>Root cause analysis</li>
<li>Vendor coordination</li>
<li>Team leadership</li>
<li>Process improvement</li>
</ul>
</div>
</div>
</article>
<!-- Education + Accomplishments -->
<!-- Education -->
<article class="card h-full">
<h2 class="text-2xl font-semibold">Education</h2>
<div class="mt-4">
@@ -81,14 +92,6 @@
<p class="text-white/70">BBA in Computer Information Systems</p>
<p class="text-white/60 text-sm mt-1">Expected May 2026</p>
</div>
<div class="mt-8 border-t border-[rgb(var(--border))] pt-6">
<h3 class="text-lg font-semibold">Accomplishments</h3>
<ul class="mt-3 text-white/80 space-y-2 list-disc pl-5">
<li>Eagle Scout (Dec 2021)</li>
<li>National Youth Leadership Training (20172019)</li>
</ul>
</div>
</article>
</div>
</section>
@@ -99,63 +102,79 @@
<article class="card">
<h2 class="text-2xl font-semibold">Experience</h2>
<!-- Current role -->
<!-- AMA TechTel -->
<div class="mt-6 relative pl-6">
<div class="absolute left-0 top-2 h-2 w-2 rounded-full bg-[rgb(var(--accent))]"></div>
<div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1">
<p class="font-medium">E-Commerce Manager — United Supermarkets #532</p>
<p class="text-white/60 text-sm">Aug 2025 Present</p>
<p class="font-medium">Level II Technical Support · AMA TechTel</p>
<p class="text-white/60 text-sm">Mar 2026 Present</p>
</div>
<p class="text-white/80">Canyon, TX</p>
<p class="text-white/80">Amarillo, TX</p>
<ul class="mt-2 text-white/70 space-y-1 list-disc pl-5">
<li>Own day-to-day online grocery operations (order flow, substitutions, delivery/pickup SLA).</li>
<li>Lead and schedule the e-commerce team; coach on accuracy, speed, and CX.</li>
<li>Monitor inventory/pricing anomalies and coordinate fixes with department leads.</li>
<li>Track KPIs (fill rate, OTIF, cancels, customer feedback) and drive process improvements.</li>
<li>Partner with IT/vendors to keep handhelds, printers, and store systems humming.</li>
<li>Provide L2 support for a CLEC network managing Cambium fixed wireless and Adtran fiber equipment; diagnose and resolve connectivity, hardware, and provisioning issues via inbound phone support.</li>
<li>Document cases, resolutions, and escalation paths in Rev.io ticketing system with consistent root-cause and resolution detail.</li>
<li>Coordinate escalations with fiber resellers and dispatch/on-site technicians for issues requiring physical remediation.</li>
</ul>
</div>
<!-- Internship (closed out) -->
<!-- Hutchinson County -->
<div class="mt-8 relative pl-6">
<div class="absolute left-0 top-2 h-2 w-2 rounded-full bg-white/40"></div>
<div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1">
<p class="font-medium">IT Intern / Junior System Administrator Hutchinson County Court House</p>
<p class="font-medium">IT Intern / Junior System Administrator · Hutchinson County Court House</p>
<p class="text-white/60 text-sm">May 2025 Aug 2025</p>
</div>
<p class="text-white/80">Stinnett, TX</p>
<ul class="mt-2 text-white/70 space-y-1 list-disc pl-5">
<li>Assisted with Windows Server/Active Directory admin and routine maintenance.</li>
<li>Resolved helpdesk tickets; imaged PCs and handled hardware/software issues.</li>
<li>Helped configure switches/APs/firewall rules; supported backups and updates.</li>
<li>Contributed to security policy rollouts and small infrastructure upgrades.</li>
<li>Assisted with Windows Server and Active Directory administration — user accounts, GPO, and routine maintenance.</li>
<li>Resolved helpdesk tickets; imaged and deployed PCs; handled hardware and software troubleshooting.</li>
<li>Configured managed switches, wireless APs, and firewall rules in a county government (regulated) environment; supported patching, backups, and security policy rollouts.</li>
</ul>
</div>
<!-- Earlier roles (optional condensed) -->
<!-- United Supermarkets -->
<div class="mt-8 relative pl-6">
<div class="absolute left-0 top-2 h-2 w-2 rounded-full bg-white/20"></div>
<div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1">
<p class="font-medium">United Supermarkets &amp; The Pergola Shop — Various Roles</p>
<p class="text-white/60 text-sm">2019 2025</p>
<p class="font-medium">E-Commerce Dept. Manager &amp; Various Roles · United Supermarkets</p>
<p class="text-white/60 text-sm">Nov 2019 Mar 2026</p>
</div>
<p class="text-white/80">Canyon &amp; Borger, TX</p>
<ul class="mt-2 text-white/70 space-y-1 list-disc pl-5">
<li>Bookkeeper, Lead Stocker, Wood Cutter — leadership, reliability, and strong customer service.</li>
<li>Advanced from Sacker (2019) → Grocery Team Lead (2022), then Service Desk Clerk/Bookkeeper during college.</li>
<li>Promoted to E-Commerce Department Manager (Aug 2025 Mar 2026); owned online order flow, delivery/pickup SLA, team scheduling, and KPI tracking (fill rate, OTIF, cancellations).</li>
<li>Partnered with IT and vendors to maintain handheld devices, printers, and store systems; first point of contact for technology issues on the floor.</li>
</ul>
</div>
</article>
</div>
</section>
<!-- Projects & Homelab -->
<section class="pb-16">
<div class="container-page">
<article class="card max-w-4xl">
<h2 class="text-2xl font-semibold">Accomplishments</h2>
<ul class="mt-3 text-white/80 space-y-2 list-disc pl-5">
<li>Eagle Scout (Dec 2021)</li>
<li>National Youth Leadership Training (20172019)</li>
</ul>
<article class="card">
<h2 class="text-2xl font-semibold">Projects &amp; Homelab</h2>
<!-- Proxmox Homelab -->
<div class="mt-6">
<p class="font-medium">Proxmox Homelab — Windows Server / Active Directory &amp; Linux</p>
<ul class="mt-2 text-white/70 space-y-1 list-disc pl-5">
<li>Self-managed Proxmox host running a Windows Server VM with AD DS and a Linux NAS providing Samba, Gitea, and Syncthing; configured Entra ID Connect to sync on-prem AD to a Microsoft 365 developer tenant.</li>
<li>Manages VM provisioning, snapshots, network segmentation, patching, and a self-hosted credential vault with client-side encryption (security-first design practice).</li>
</ul>
</div>
<!-- BillFlow -->
<div class="mt-6">
<div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1">
<p class="font-medium">BillFlow — Self-Hosted SaaS Invoicing Platform</p>
<a href="https://netdeploy.net" target="_blank" rel="noopener" class="text-[rgb(var(--accent))] text-sm hover:underline">netdeploy.net</a>
</div>
<ul class="mt-2 text-white/70 space-y-1 list-disc pl-5">
<li>Built and deployed a multi-tenant invoicing platform (Flask/SQLite, nginx/Gunicorn, Vultr VPS); managed full deployment lifecycle including TLS, reverse proxy config, and ongoing maintenance.</li>
</ul>
</div>
</article>
</div>
</section>

View File

@@ -3,6 +3,22 @@
{% block content %}
{% if blogpost.draft %}
<div class="bg-yellow-500/20 border-b border-yellow-400/40 text-yellow-300 px-6 py-3 flex items-center justify-between gap-4">
<span class="font-semibold">&#9888; This post is a draft — only you can see it.</span>
<div class="flex gap-3">
<a href="{{ url_for('edit_blog', slug=blogpost.slug) }}"
class="bg-white/10 hover:bg-white/20 text-white text-sm px-4 py-1.5 rounded transition">Edit</a>
<form action="{{ url_for('publish_blog', slug=blogpost.slug) }}" method="post">
<button type="submit"
class="bg-orange-500 hover:bg-orange-600 text-white text-sm px-4 py-1.5 rounded transition">
Publish Post
</button>
</form>
</div>
</div>
{% endif %}
<!-- Hero -->
<section class="py-20 text-center text-white bg-gradient-to-br from-orange-500/20 via-rose-500/10 to-fuchsia-500/10 backdrop-blur border-b border-white/10">
<div class="max-w-3xl mx-auto px-6">
@@ -50,7 +66,7 @@
<!-- Content -->
<article class="prose prose-invert max-w-none leading-relaxed">
{{ blogpost.content | safe }}
{{ blogpost.content | markdown | safe }}
</article>
<div class="pt-2">

View File

@@ -3,6 +3,22 @@
{% block content %}
{% if projectpost.draft %}
<div class="bg-yellow-500/20 border-b border-yellow-400/40 text-yellow-300 px-6 py-3 flex items-center justify-between gap-4">
<span class="font-semibold">&#9888; This post is a draft — only you can see it.</span>
<div class="flex gap-3">
<a href="{{ url_for('edit_project', slug=projectpost.slug) }}"
class="bg-white/10 hover:bg-white/20 text-white text-sm px-4 py-1.5 rounded transition">Edit</a>
<form action="{{ url_for('publish_project', slug=projectpost.slug) }}" method="post">
<button type="submit"
class="bg-orange-500 hover:bg-orange-600 text-white text-sm px-4 py-1.5 rounded transition">
Publish Post
</button>
</form>
</div>
</div>
{% endif %}
<!-- Hero Section -->
<section class="py-20 text-center text-white bg-gradient-to-br from-orange-500/20 via-rose-500/10 to-fuchsia-500/10 backdrop-blur border-b border-white/10">
<div class="max-w-3xl mx-auto px-6">
@@ -48,7 +64,7 @@
<!-- Content -->
<article class="prose prose-invert max-w-none leading-relaxed">
{{ projectpost.content | safe }}
{{ projectpost.content | markdown | safe }}
</article>
<div class="pt-2">