mirror of
https://github.com/tomru/pdfer.git
synced 2026-03-03 06:27:19 +01:00
fix all type errors
This commit is contained in:
@@ -1,96 +1,83 @@
|
||||
import React, { Component } from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import LetterOptions from './LetterOptions'
|
||||
import Button from './Button'
|
||||
import Preview from './Preview'
|
||||
import LatestList from './LatestList'
|
||||
import { generatePdf, getLatest, removeLatest } from './apiHelper'
|
||||
import { ILatest } from '../interfaces/ILatest'
|
||||
import { IDocProps } from '../interfaces/IDocProps'
|
||||
|
||||
//import './App.css';
|
||||
|
||||
class App extends Component {
|
||||
componentDidMount() {
|
||||
this._getLatest()
|
||||
}
|
||||
|
||||
render() {
|
||||
const state: Record<string, unknown> = this.state || {}
|
||||
|
||||
return (
|
||||
<div className="home">
|
||||
<div>
|
||||
<LetterOptions onChange={this._onChange.bind(this)} {...state.options} />
|
||||
<LatestList
|
||||
latest={state.latest}
|
||||
onSelect={this._onSelectLatest.bind(this)}
|
||||
onRemove={this._onRemoveLatest.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<Button onClick={this._onGenerate.bind(this)}>Backe PDF</Button>
|
||||
<Button onClick={this._onClear.bind(this)}>Alles Löschen</Button>
|
||||
</div>
|
||||
<Preview pdfUrl={state.pdfUrl} pdfIsLoading={state.pdfIsLoading} pdfError={state.pdfError} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
_onSelectLatest(selectedOptions) {
|
||||
this.setState({ options: Object.assign({}, selectedOptions) })
|
||||
}
|
||||
|
||||
_onRemoveLatest(item) {
|
||||
removeLatest(item).then(() => {
|
||||
const latest = this.state.latest.filter((curr) => curr.id !== item.id)
|
||||
|
||||
this.setState({ latest })
|
||||
export default function App() {
|
||||
const [options, setOptions] = useState<IDocProps>({
|
||||
template: 'brief-fam',
|
||||
subject: '',
|
||||
body: '',
|
||||
address: '',
|
||||
})
|
||||
}
|
||||
const [latest, setLatest] = useState<ILatest[]>([])
|
||||
const [pdfUrl, setPdfUrl] = useState<string | null>(null)
|
||||
const [pdfIsLoading, setPdfIsLoading] = useState<boolean>(false)
|
||||
const [pdfError, setPdfError] = useState<string | null>(null)
|
||||
|
||||
_onClear() {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
_onGenerate() {
|
||||
const state = this.state || {}
|
||||
this.setState({
|
||||
pdfIsLoading: true,
|
||||
pdfError: null,
|
||||
})
|
||||
|
||||
generatePdf(state.options)
|
||||
.then((data) => {
|
||||
const { id } = data
|
||||
this.setState({
|
||||
pdfIsLoading: false,
|
||||
pdfUrl: `/api/pdf/${id}`,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({
|
||||
pdfIsLoading: false,
|
||||
pdfError: error.message,
|
||||
pdfUrl: null,
|
||||
})
|
||||
})
|
||||
.then(() => this._getLatest())
|
||||
}
|
||||
|
||||
_getLatest() {
|
||||
useEffect(() => {
|
||||
getLatest()
|
||||
.then((latest) => this.setState({ latest }))
|
||||
.then((latest) => setLatest(latest))
|
||||
.catch((err) => console.error('Unable to get latest:', err))
|
||||
}
|
||||
}, [pdfUrl])
|
||||
|
||||
_onChange(name, event) {
|
||||
const _onChange = (name: string, event: React.ChangeEvent<{ value: string }>) => {
|
||||
if (!name) {
|
||||
return
|
||||
}
|
||||
const value = event && event.target && event.target.value
|
||||
const options = Object.assign({}, this.state.options, { [name]: value || undefined })
|
||||
this.setState({ options })
|
||||
setOptions({ ...options, [name]: value || undefined })
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
const _onSelectLatest = (selectedOption: ILatest) => {
|
||||
setOptions({ ...selectedOption })
|
||||
}
|
||||
|
||||
const _onRemoveLatest = (item: ILatest) => {
|
||||
removeLatest(item).then(() => setLatest(latest.filter((curr) => curr.id !== item.id)))
|
||||
}
|
||||
|
||||
const _onClear = () => {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
const _onGenerate = () => {
|
||||
setPdfIsLoading(true)
|
||||
setPdfError(null)
|
||||
|
||||
generatePdf(options)
|
||||
.then((data) => {
|
||||
const { id } = data
|
||||
|
||||
setPdfIsLoading(false)
|
||||
setPdfUrl(`/api/pdf/${id}`)
|
||||
})
|
||||
.catch((error) => {
|
||||
setPdfIsLoading(false)
|
||||
setPdfError(error.message)
|
||||
setPdfUrl(null)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="home">
|
||||
<div>
|
||||
<LetterOptions onChange={_onChange} {...options} />
|
||||
<LatestList latest={latest} onSelect={_onSelectLatest} onRemove={_onRemoveLatest} />
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<Button onClick={_onGenerate}>Backe PDF</Button>
|
||||
<Button onClick={_onClear}>Alles Löschen</Button>
|
||||
</div>
|
||||
<Preview pdfUrl={pdfUrl} pdfIsLoading={pdfIsLoading} pdfError={pdfError} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@ import React from 'react'
|
||||
export default function Input({
|
||||
text,
|
||||
name,
|
||||
value,
|
||||
value = '',
|
||||
placeholder,
|
||||
onchange,
|
||||
}: {
|
||||
text: string
|
||||
name: string
|
||||
value: string
|
||||
placeholder: string
|
||||
onchange: () => void
|
||||
value?: string
|
||||
placeholder?: string
|
||||
onchange: (name: string, event: React.ChangeEvent<HTMLInputElement>) => void
|
||||
}) {
|
||||
return (
|
||||
<label>
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IDocProps } from '../interfaces/IDocProps'
|
||||
const EXAMPLE_ADDRESS = 'Max Mustermann\nMusterstr. 73\n12345 Musterstadt'
|
||||
|
||||
interface IProps extends IDocProps {
|
||||
onChange: () => void
|
||||
onChange: (name: string, event: React.ChangeEvent<{ value: string }>) => void
|
||||
}
|
||||
|
||||
export default function LetterOptions(props: IProps) {
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import React from 'react'
|
||||
import { IPdfProps } from '../interfaces/IPdfProps'
|
||||
|
||||
export default function Preview({
|
||||
pdfIsLoading,
|
||||
pdfError,
|
||||
pdfUrl,
|
||||
}: {
|
||||
pdfIsLoading: boolean
|
||||
pdfError: string
|
||||
pdfUrl: string
|
||||
}) {
|
||||
export default function Preview({ pdfIsLoading, pdfError, pdfUrl }: IPdfProps) {
|
||||
if (pdfIsLoading) {
|
||||
return <div>Lade…</div>
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function Select({
|
||||
name: string
|
||||
text: string
|
||||
value: string
|
||||
onchange: () => void
|
||||
onchange: (name: string, event: React.ChangeEvent<{ value: string }>) => void
|
||||
options: { name: string; value: string }[]
|
||||
}) {
|
||||
return (
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function TextAreaInput({
|
||||
text: string
|
||||
name: string
|
||||
placeholder: string
|
||||
onchange: () => void
|
||||
onchange: (name: string, event: React.ChangeEvent<HTMLTextAreaElement>) => void
|
||||
value: string
|
||||
}) {
|
||||
return (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { IDocProps } from '../interfaces/IDocProps'
|
||||
import { ILatest } from '../interfaces/ILatest'
|
||||
|
||||
function checkStatus(res: Response) {
|
||||
@@ -6,7 +7,7 @@ function checkStatus(res: Response) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function generatePdf(state: Record<string, string>) {
|
||||
export async function generatePdf(state: IDocProps) {
|
||||
const options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
||||
5
interfaces/IPdfProps.ts
Normal file
5
interfaces/IPdfProps.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface IPdfProps {
|
||||
pdfUrl: string | null
|
||||
pdfIsLoading: boolean
|
||||
pdfError: string | null
|
||||
}
|
||||
@@ -2,6 +2,7 @@ const storeDir = process.env.JSON_STORE || '/tmp/pdfer-store/'
|
||||
|
||||
import { promisify } from 'util'
|
||||
|
||||
// @ts-ignore
|
||||
import JsonStore from 'json-fs-store'
|
||||
|
||||
const store = JsonStore(storeDir)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { IDocProps } from '../interfaces/IDocProps'
|
||||
|
||||
function convertLineBreaks(lines: string) {
|
||||
return lines.replace(/\n/g, '\\\\')
|
||||
}
|
||||
|
||||
export function brief(options: Record<string, string>) {
|
||||
export function brief(options: IDocProps) {
|
||||
const {
|
||||
template = 'brief-fam',
|
||||
subject = '',
|
||||
@@ -21,7 +23,7 @@ export function brief(options: Record<string, string>) {
|
||||
closing = 'Mit freundlichen Grüßen',
|
||||
ps = '',
|
||||
enclosing = '',
|
||||
} = options
|
||||
} = { ...options }
|
||||
|
||||
return `% brief document
|
||||
\\documentclass{scrlttr2}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {promises} from 'fs'
|
||||
import { promises } from 'fs'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
import {remove as storeRemove} from '../../../lib/store'
|
||||
import { remove as storeRemove } from '../../../lib/store'
|
||||
import { getPdfPath } from '../../../lib/utils'
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
const { method } = req
|
||||
|
||||
switch (req.method) {
|
||||
case 'GET':
|
||||
@@ -14,14 +14,16 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
query: { id: idArg },
|
||||
} = req
|
||||
|
||||
const fileContent = await promises.readFile(getPdfPath(idArg))
|
||||
const id = Array.isArray(idArg) ? idArg[0] : idArg
|
||||
|
||||
const fileContent = await promises.readFile(getPdfPath(id))
|
||||
res.setHeader('Content-Type', 'application/pdf')
|
||||
res.status(200).send(fileContent);
|
||||
res.status(200).send(fileContent)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
res.status(404).json({ statusCode: 404, message: 'Method Not Allowed' })
|
||||
}
|
||||
break;
|
||||
break
|
||||
case 'DELETE':
|
||||
try {
|
||||
const {
|
||||
@@ -35,11 +37,11 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
console.error(error)
|
||||
res.status(404).json({ statusCode: 404, message: 'Method Not Allowed' })
|
||||
}
|
||||
break;
|
||||
break
|
||||
default:
|
||||
res.setHeader('Allow', ['GET', 'DELETE'])
|
||||
res.status(405).end(`Method ${method} Not Allowed`)
|
||||
}
|
||||
}
|
||||
|
||||
export default handler;
|
||||
export default handler
|
||||
|
||||
@@ -2,7 +2,7 @@ import Layout from '../components/Layout'
|
||||
import App from '../components/App'
|
||||
|
||||
const IndexPage = () => (
|
||||
<Layout title="Home | Next.js + TypeScript Example">
|
||||
<Layout>
|
||||
<App />
|
||||
</Layout>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user