created SaveFileUploadDialog and SaveParserBackendService
This commit is contained in:
parent
c216250eca
commit
9faf3f7618
@ -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
11
src/app/page.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -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">
|
||||||
|
|||||||
13
src/components/FormError.tsx
Normal file
13
src/components/FormError.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
79
src/components/SaveFileUploadingDialog.tsx
Normal file
79
src/components/SaveFileUploadingDialog.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
55
src/services/SaveParserBackendService.ts
Normal file
55
src/services/SaveParserBackendService.ts
Normal 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()
|
||||||
Loading…
Reference in New Issue
Block a user