87 lines
3.2 KiB
TypeScript
87 lines
3.2 KiB
TypeScript
import React from 'react'
|
|
import { t } from '@/lib/i18n'
|
|
import type { ReviewTipFormController } from './useReviewTipFormController'
|
|
|
|
export function ReviewTipFormView(params: { ctrl: ReviewTipFormController; onCancel?: () => void }): React.ReactElement {
|
|
return (
|
|
<form
|
|
onSubmit={(e) => void params.ctrl.handleSubmit(e)}
|
|
className="border border-neon-cyan/30 rounded-lg p-4 bg-cyber-dark space-y-4"
|
|
>
|
|
<ReviewTipFormHeader split={params.ctrl.split} />
|
|
<ReviewTipTextField value={params.ctrl.text} onChange={params.ctrl.setText} />
|
|
{params.ctrl.error ? <ErrorBox message={params.ctrl.error} /> : null}
|
|
<ReviewTipFormActions amount={params.ctrl.split.total} loading={params.ctrl.loading} onCancel={params.onCancel} />
|
|
</form>
|
|
)
|
|
}
|
|
|
|
function ReviewTipFormHeader(params: { split: { total: number; reviewer: number; platform: number } }): React.ReactElement {
|
|
return (
|
|
<>
|
|
<h3 className="text-lg font-semibold text-neon-cyan">{t('reviewTip.form.title')}</h3>
|
|
<p className="text-sm text-cyber-accent/70">
|
|
{t('reviewTip.form.description', {
|
|
amount: params.split.total,
|
|
reviewer: params.split.reviewer,
|
|
platform: params.split.platform,
|
|
})}
|
|
</p>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function ReviewTipTextField(params: { value: string; onChange: (value: string) => void }): React.ReactElement {
|
|
return (
|
|
<div>
|
|
<label htmlFor="review-tip-text" className="block text-sm font-medium text-cyber-accent mb-1">
|
|
{t('reviewTip.form.text.label')} <span className="text-cyber-accent/50">({t('common.optional')})</span>
|
|
</label>
|
|
<textarea
|
|
id="review-tip-text"
|
|
value={params.value}
|
|
onChange={(e) => params.onChange(e.target.value)}
|
|
placeholder={t('reviewTip.form.text.placeholder')}
|
|
rows={3}
|
|
className="w-full px-3 py-2 bg-cyber-darker border border-neon-cyan/30 rounded text-cyber-accent focus:border-neon-cyan focus:outline-none"
|
|
/>
|
|
<p className="text-xs text-cyber-accent/70 mt-1">{t('reviewTip.form.text.help')}</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function ReviewTipFormActions(params: {
|
|
amount: number
|
|
loading: boolean
|
|
onCancel?: (() => void) | undefined
|
|
}): React.ReactElement {
|
|
return (
|
|
<div className="flex gap-2">
|
|
<button
|
|
type="submit"
|
|
disabled={params.loading}
|
|
className="px-4 py-2 bg-neon-green/20 hover:bg-neon-green/30 text-neon-green rounded-lg font-medium transition-all border border-neon-green/50 hover:shadow-glow-green disabled:opacity-50"
|
|
>
|
|
{params.loading ? t('common.loading') : t('reviewTip.form.submit', { amount: params.amount })}
|
|
</button>
|
|
{params.onCancel ? (
|
|
<button
|
|
type="button"
|
|
onClick={params.onCancel}
|
|
className="px-4 py-2 bg-cyber-darker hover:bg-cyber-dark text-cyber-accent rounded-lg font-medium transition-all border border-neon-cyan/30"
|
|
>
|
|
{t('common.cancel')}
|
|
</button>
|
|
) : null}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function ErrorBox({ message }: { message: string }): React.ReactElement {
|
|
return (
|
|
<div className="p-3 bg-red-900/20 border border-red-500/50 rounded text-red-400 text-sm">
|
|
{message}
|
|
</div>
|
|
)
|
|
}
|