created SaveFileUploadDialog and SaveParserBackendService

This commit is contained in:
Altair-sh 2025-05-22 17:09:44 +05:00
parent c216250eca
commit 9faf3f7618
6 changed files with 166 additions and 14 deletions

View File

@ -1,7 +1,8 @@
'use client' 'use client'
import { useState } from 'react' import { useState } from 'react'
import { authService } from '@/services/authService' import { authService } from '@/services/AuthService'
import FormError from '@/components/FormError'
export default function LoginPage() { export default function LoginPage() {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@ -10,7 +11,7 @@ export default function LoginPage() {
stayLoggedIn: true, stayLoggedIn: true,
}) })
const [error, setError] = useState('') const [error, setError] = useState<string | null>(null)
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value, type, checked } = e.target const { name, value, type, checked } = e.target
@ -36,11 +37,7 @@ export default function LoginPage() {
<div className="container mt-5" style={{ maxWidth: '500px' }}> <div className="container mt-5" style={{ maxWidth: '500px' }}>
<h2 className="mb-4">Login</h2> <h2 className="mb-4">Login</h2>
{error && ( <FormError message={error} />
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="mb-3"> <div className="mb-3">

11
src/app/page.tsx Normal file
View File

@ -0,0 +1,11 @@
import SaveFileUploadingDialog from '@/components/SaveFileUploadingDialog'
export default function HomePage() {
return (
<div className="container mt-5 text-center">
<h1 className="mb-4">Welcome to Paradox Save Parser!</h1>
<SaveFileUploadingDialog />
</div>
)
}

View File

@ -2,7 +2,8 @@
import { useState } from 'react' import { useState } from 'react'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { authService } from '@/services/authService' import { authService } from '@/services/AuthService'
import FormError from '@/components/FormError'
export default function RegisterPage() { export default function RegisterPage() {
const router = useRouter() const router = useRouter()
@ -14,7 +15,7 @@ export default function RegisterPage() {
confirmPassword: '', confirmPassword: '',
}) })
const [error, setError] = useState('') const [error, setError] = useState<string | null>(null)
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFormData((prev) => ({ setFormData((prev) => ({
@ -45,11 +46,7 @@ export default function RegisterPage() {
<div className="container mt-5" style={{ maxWidth: '400px' }}> <div className="container mt-5" style={{ maxWidth: '400px' }}>
<h2 className="mb-4 text-center">Register</h2> <h2 className="mb-4 text-center">Register</h2>
{error && ( <FormError message={error} />
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="mb-3"> <div className="mb-3">

View File

@ -0,0 +1,13 @@
interface FormErrorProps {
message: string | null
}
export default function FormError(props: FormErrorProps) {
if (!props.message || props.message === '') return null
return (
<div className="alert alert-danger" role="alert">
{props.message}
</div>
)
}

View File

@ -0,0 +1,79 @@
'use client'
import { saveParserBackendService, UploadSaveResponse } from '@/services/SaveParserBackendService'
import { useState } from 'react'
import FormError from './FormError'
export enum GameEnum {
EU4 = 'eu4',
Stellaris = 'stellaris',
}
export default function SaveFileUploadingDialog() {
const [error, setError] = useState<string | null>(null)
const [selectedFile, setSelectedFile] = useState<File | null>(null)
const [game, setGame] = useState<GameEnum>(GameEnum.EU4)
const [uploadResult, setUploadResult] = useState<UploadSaveResponse | null>(null)
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files[0]) {
setSelectedFile(e.target.files[0])
}
}
const handleUpload = async () => {
try {
if (!selectedFile) return
console.log('Uploading file:', selectedFile.name)
const result = await saveParserBackendService.uploadSave(game, selectedFile)
console.log('Got response:', result)
setUploadResult(result)
} catch (err: any) {
console.error(err.message)
setError(err.message)
}
}
return (
<div className="container mt-5" style={{ maxWidth: '500px' }}>
<h3 className="mb-2 fw-semibold">Select game save file</h3>
<FormError message={error} />
<div className="mb-3">
<label htmlFor="gameSelect" className="form-label">
Select Game
</label>
<select
id="gameSelect"
className="form-select"
value={game}
onChange={(e) => setGame(e.target.value as GameEnum)}
>
{Object.values(GameEnum).map((value) => (
<option key={value} value={value}>
{value}
</option>
))}
</select>
</div>
<input type="file" className="form-control mb-3" onChange={handleFileChange} />
<button className="btn btn-primary" onClick={handleUpload} disabled={!selectedFile}>
Upload File
</button>
{selectedFile && (
<div className="mt-3">
File: <strong>{selectedFile.name}</strong>
</div>
)}
{uploadResult && (
<div className="mt-3">
Save Id: <strong>{uploadResult.id}</strong>
</div>
)}
</div>
)
}

View File

@ -0,0 +1,55 @@
export interface UploadSaveResponse {
id: string
}
export interface SaveStatusResponse {
id: string
game: string
status: string
uploadDateTime: string
}
export class SaveParserBackendService {
private API_BASE = 'http://localhost:5226'
async uploadSave(game: string, file: File): Promise<UploadSaveResponse> {
const url = `${this.API_BASE}/uploadSave?game=${encodeURIComponent(game)}`
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
body: file,
})
if (!response.ok) {
throw new Error(`Failed to upload save: ${response.statusText} \n${await response.text()}`)
}
return await response.json()
}
async getSaveStatus(id: string): Promise<SaveStatusResponse> {
const url = `${this.API_BASE}/getSaveStatus?id=${encodeURIComponent(id)}`
const response = await fetch(url)
if (!response.ok) {
throw new Error(`Failed to get save status: ${response.statusText} \n${await response.text()}`)
}
return await response.json()
}
async getParsedSave(id: string): Promise<Record<string, any>> {
const url = `${this.API_BASE}/getParsedSave?id=${encodeURIComponent(id)}`
const response = await fetch(url)
if (!response.ok) {
throw new Error(`Failed to get parsed save: ${response.statusText} \n${await response.text()}`)
}
return await response.json()
}
}
export const saveParserBackendService = new SaveParserBackendService()