project-nomad/admin/inertia/components/DownloadURLModal.tsx
Chris Sherwood e8d775dfe4 feat(UI): add Night Ops dark mode with theme toggle
Add a warm charcoal dark mode ("Night Ops") using CSS variable swapping
under [data-theme="dark"]. All 23 desert palette variables are overridden
with dark-mode counterparts, and ~313 generic Tailwind classes (bg-white,
text-gray-*, border-gray-*) are replaced with semantic tokens.

Infrastructure:
- CSS variable overrides in app.css for both themes
- ThemeProvider + useTheme hook (localStorage + KV store sync)
- ThemeToggle component (moon/sun icons, "Night Ops"/"Day Ops" labels)
- FOUC prevention script in inertia_layout.edge
- Toggle placed in StyledSidebar and Footer for access on every page

Color replacements across 50 files:
- bg-white → bg-surface-primary
- bg-gray-50/100 → bg-surface-secondary
- text-gray-900/800 → text-text-primary
- text-gray-600/500 → text-text-secondary/text-text-muted
- border-gray-200/300 → border-border-subtle/border-border-default
- text-desert-white → text-white (fixes invisible text on colored bg)
- Button hover/active states use dedicated btn-green-hover/active vars

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 09:17:05 -07:00

95 lines
2.8 KiB
TypeScript

import { useState } from 'react'
import StyledModal, { StyledModalProps } from './StyledModal'
import Input from './inputs/Input'
import api from '~/lib/api'
export type DownloadURLModalProps = Omit<
StyledModalProps,
'onConfirm' | 'open' | 'confirmText' | 'cancelText' | 'confirmVariant' | 'children'
> & {
suggestedURL?: string
onPreflightSuccess?: (url: string) => void
}
const DownloadURLModal: React.FC<DownloadURLModalProps> = ({
suggestedURL,
onPreflightSuccess,
...modalProps
}) => {
const [url, setUrl] = useState<string>('')
const [messages, setMessages] = useState<string[]>([])
const [loading, setLoading] = useState<boolean>(false)
async function runPreflightCheck(downloadUrl: string) {
try {
setLoading(true)
setMessages([`Running preflight check for URL: ${downloadUrl}`])
const res = await api.downloadRemoteMapRegionPreflight(downloadUrl)
if (!res) {
throw new Error('An unknown error occurred during the preflight check.')
}
if ('message' in res) {
throw new Error(res.message)
}
setMessages((prev) => [
...prev,
`Preflight check passed. Filename: ${res.filename}, Size: ${(res.size / (1024 * 1024)).toFixed(2)} MB`,
])
if (onPreflightSuccess) {
onPreflightSuccess(downloadUrl)
}
} catch (error) {
console.error('Preflight check failed:', error)
setMessages((prev) => [...prev, `Preflight check failed: ${error.message}`])
} finally {
setLoading(false)
}
}
return (
<StyledModal
{...modalProps}
onConfirm={() => runPreflightCheck(url)}
open={true}
confirmText="Download"
confirmIcon="IconDownload"
cancelText="Cancel"
confirmVariant="primary"
confirmLoading={loading}
cancelLoading={loading}
large
>
<div className="flex flex-col pb-4">
<p className="text-text-secondary mb-8">
Enter the URL of the map region file you wish to download. The URL must be publicly
reachable and end with .pmtiles. A preflight check will be run to verify the file's
availability, type, and approximate size.
</p>
<Input
name="download-url"
label=""
placeholder={suggestedURL || 'Enter download URL...'}
className="mb-4"
value={url}
onChange={(e) => setUrl(e.target.value)}
/>
<div className="min-h-24 max-h-96 overflow-y-auto bg-surface-secondary p-4 rounded border border-border-default text-left">
{messages.map((message, idx) => (
<p
key={idx}
className="text-sm text-text-primary font-mono leading-relaxed break-words mb-3"
>
{message}
</p>
))}
</div>
</div>
</StyledModal>
)
}
export default DownloadURLModal