|
@@ -1,9 +1,10 @@
|
|
|
-import { useState, type FormEvent } from 'react'
|
|
|
|
|
-import { Link } from 'react-router-dom'
|
|
|
|
|
|
|
+import { useEffect, useState, type FormEvent } from 'react'
|
|
|
|
|
+import { Link, useParams } from 'react-router-dom'
|
|
|
import { Helmet } from 'react-helmet-async'
|
|
import { Helmet } from 'react-helmet-async'
|
|
|
-import { createCustomer } from '../../../services/api/customers'
|
|
|
|
|
|
|
+import { createCustomer, getCustomerById, updateCustomer } from '../../../services/api/customers'
|
|
|
import { uploadMedia } from '../../../services/api/media'
|
|
import { uploadMedia } from '../../../services/api/media'
|
|
|
import {
|
|
import {
|
|
|
|
|
+ customerToFormValues,
|
|
|
emptyCustomerForm,
|
|
emptyCustomerForm,
|
|
|
formValuesToPayload,
|
|
formValuesToPayload,
|
|
|
type CustomerFormValues,
|
|
type CustomerFormValues,
|
|
@@ -29,6 +30,7 @@ function getSubmitErrorMessage(error: unknown, locale: 'zh' | 'ja') {
|
|
|
|
|
|
|
|
export function CustomerFormPage() {
|
|
export function CustomerFormPage() {
|
|
|
const { locale, navigate, path, copy } = usePageContext()
|
|
const { locale, navigate, path, copy } = usePageContext()
|
|
|
|
|
+ const { customerId } = useParams()
|
|
|
const [form, setForm] = useState<CustomerFormValues>(emptyCustomerForm)
|
|
const [form, setForm] = useState<CustomerFormValues>(emptyCustomerForm)
|
|
|
const [submitting, setSubmitting] = useState(false)
|
|
const [submitting, setSubmitting] = useState(false)
|
|
|
const [error, setError] = useState('')
|
|
const [error, setError] = useState('')
|
|
@@ -37,7 +39,16 @@ export function CustomerFormPage() {
|
|
|
|
|
|
|
|
const patch = (part: Partial<CustomerFormValues>) => setForm((current) => ({ ...current, ...part }))
|
|
const patch = (part: Partial<CustomerFormValues>) => setForm((current) => ({ ...current, ...part }))
|
|
|
const pageCopy = copy.customerFormPage
|
|
const pageCopy = copy.customerFormPage
|
|
|
- const modeCopy = pageCopy.new
|
|
|
|
|
|
|
+ const isEditMode = Boolean(customerId)
|
|
|
|
|
+ const modeCopy = isEditMode ? pageCopy.edit : pageCopy.new
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ if (!customerId) return
|
|
|
|
|
+
|
|
|
|
|
+ getCustomerById(customerId)
|
|
|
|
|
+ .then((customer) => setForm(customerToFormValues(customer)))
|
|
|
|
|
+ .catch(() => setError(locale === 'ja' ? '顧客情報の取得に失敗しました' : '获取顾客信息失败'))
|
|
|
|
|
+ }, [customerId, locale])
|
|
|
|
|
|
|
|
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
|
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
|
|
event.preventDefault()
|
|
event.preventDefault()
|
|
@@ -48,8 +59,13 @@ export function CustomerFormPage() {
|
|
|
let avatar: string | undefined
|
|
let avatar: string | undefined
|
|
|
if (photoFile) avatar = (await uploadMedia(photoFile, 'avatar')).url
|
|
if (photoFile) avatar = (await uploadMedia(photoFile, 'avatar')).url
|
|
|
const payload = formValuesToPayload(form, avatar)
|
|
const payload = formValuesToPayload(form, avatar)
|
|
|
- await createCustomer(payload)
|
|
|
|
|
- navigate(path('/customers'))
|
|
|
|
|
|
|
+ if (isEditMode && customerId) {
|
|
|
|
|
+ await updateCustomer(customerId, payload)
|
|
|
|
|
+ navigate(path(`/customers/${customerId}`))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await createCustomer(payload)
|
|
|
|
|
+ navigate(path('/customers'))
|
|
|
|
|
+ }
|
|
|
} catch (err) {
|
|
} catch (err) {
|
|
|
setError(getSubmitErrorMessage(err, locale))
|
|
setError(getSubmitErrorMessage(err, locale))
|
|
|
} finally {
|
|
} finally {
|
|
@@ -67,9 +83,9 @@ export function CustomerFormPage() {
|
|
|
<section className="stylist-workbench-top ipad-top-space-margin mb-2">
|
|
<section className="stylist-workbench-top ipad-top-space-margin mb-2">
|
|
|
<div className="container">
|
|
<div className="container">
|
|
|
<div className="d-flex align-items-center justify-content-between flex-wrap gap-3 mb-4">
|
|
<div className="d-flex align-items-center justify-content-between flex-wrap gap-3 mb-4">
|
|
|
- <Link to={path('/customers')} className="btn btn-small btn-rounded btn-transparent-light-gray border border-1 border-color-dark-gray fw-700"><i className="feather icon-feather-arrow-left me-6px"></i>{modeCopy.back}</Link>
|
|
|
|
|
|
|
+ <Link to={isEditMode && customerId ? path(`/customers/${customerId}`) : path('/customers')} className="btn btn-small btn-rounded btn-transparent-light-gray border border-1 border-color-dark-gray fw-700"><i className="feather icon-feather-arrow-left me-6px"></i>{modeCopy.back}</Link>
|
|
|
<div className="d-flex flex-wrap gap-2">
|
|
<div className="d-flex flex-wrap gap-2">
|
|
|
- <Link to={path('/customers')} className="btn btn-large btn-rounded btn-transparent-light-gray border border-1 border-color-dark-gray fw-700">{copy.common.cancel}</Link>
|
|
|
|
|
|
|
+ <Link to={isEditMode && customerId ? path(`/customers/${customerId}`) : path('/customers')} className="btn btn-large btn-rounded btn-transparent-light-gray border border-1 border-color-dark-gray fw-700">{copy.common.cancel}</Link>
|
|
|
<button type="submit" form="customer-new-form" className="btn btn-large btn-rounded btn-base-color btn-box-shadow fw-700"><i className="feather icon-feather-user-plus me-10px"></i>{modeCopy.submit}</button>
|
|
<button type="submit" form="customer-new-form" className="btn btn-large btn-rounded btn-base-color btn-box-shadow fw-700"><i className="feather icon-feather-user-plus me-10px"></i>{modeCopy.submit}</button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -77,7 +93,7 @@ export function CustomerFormPage() {
|
|
|
<div className="workbench-panel bg-white border-radius-8px box-shadow-extra-large p-30px">
|
|
<div className="workbench-panel bg-white border-radius-8px box-shadow-extra-large p-30px">
|
|
|
<span className="bg-base-color d-inline-block mb-15px fw-600 text-white text-uppercase border-radius-30px ps-20px pe-20px fs-12">{modeCopy.badge}</span>
|
|
<span className="bg-base-color d-inline-block mb-15px fw-600 text-white text-uppercase border-radius-30px ps-20px pe-20px fs-12">{modeCopy.badge}</span>
|
|
|
<h1 className="fw-700 text-dark-gray ls-minus-1px mb-10px">{modeCopy.heading}</h1>
|
|
<h1 className="fw-700 text-dark-gray ls-minus-1px mb-10px">{modeCopy.heading}</h1>
|
|
|
- <p className="fs-18 lh-30 mb-0">{modeCopy.lead}</p>
|
|
|
|
|
|
|
+ <p className="fs-18 lh-30 mb-0">{modeCopy.lead.replace('{{name}}', form.name || '')}</p>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</section>
|
|
</section>
|
|
@@ -201,35 +217,46 @@ export function CustomerFormPage() {
|
|
|
<div className="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-25px">
|
|
<div className="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-25px">
|
|
|
<div>
|
|
<div>
|
|
|
<span className="fs-14 fw-700 text-base-color text-uppercase">{pageCopy.follow.badge}</span>
|
|
<span className="fs-14 fw-700 text-base-color text-uppercase">{pageCopy.follow.badge}</span>
|
|
|
- <h2 className="fw-700 text-dark-gray fs-26 mb-0">{pageCopy.follow.titleNew}</h2>
|
|
|
|
|
|
|
+ <h2 className="fw-700 text-dark-gray fs-26 mb-0">{pageCopy.follow.titleEdit}</h2>
|
|
|
</div>
|
|
</div>
|
|
|
- <span className="workbench-badge">{pageCopy.follow.statusNew}</span>
|
|
|
|
|
|
|
+ <span className="workbench-badge">{pageCopy.follow.statusEdit}</span>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="row g-3">
|
|
<div className="row g-3">
|
|
|
<div className="col-lg-4 col-md-6">
|
|
<div className="col-lg-4 col-md-6">
|
|
|
- <label htmlFor="follow-timing" className="customer-edit-label">{pageCopy.follow.timingNew}</label>
|
|
|
|
|
- <input id="follow-timing" type="date" className="form-control customer-edit-control" value={form.nextFollowDate} onChange={(event) => patch({ nextFollowDate: event.target.value })} />
|
|
|
|
|
|
|
+ <label htmlFor="follow-recommend-visit" className="customer-edit-label">{pageCopy.follow.timingEdit}</label>
|
|
|
|
|
+ <input id="follow-recommend-visit" type="date" className="form-control customer-edit-control" value={form.recommendVisitDate} onChange={(event) => patch({ recommendVisitDate: event.target.value })} />
|
|
|
</div>
|
|
</div>
|
|
|
<div className="col-lg-4 col-md-6">
|
|
<div className="col-lg-4 col-md-6">
|
|
|
- <label htmlFor="next-visit" className="customer-edit-label">{pageCopy.follow.nextVisitNew}</label>
|
|
|
|
|
- <input id="next-visit" type="date" className="form-control customer-edit-control" value={form.recommendVisitDate} onChange={(event) => patch({ recommendVisitDate: event.target.value })} />
|
|
|
|
|
|
|
+ <label htmlFor="follow-timing" className="customer-edit-label">{pageCopy.follow.nextVisitNew}</label>
|
|
|
|
|
+ <input id="follow-timing" type="date" className="form-control customer-edit-control" value={form.nextFollowDate} onChange={(event) => patch({ nextFollowDate: event.target.value })} />
|
|
|
</div>
|
|
</div>
|
|
|
<div className="col-lg-4 col-md-6">
|
|
<div className="col-lg-4 col-md-6">
|
|
|
- <label htmlFor="template-source" className="customer-edit-label">{pageCopy.follow.templateNew}</label>
|
|
|
|
|
- <select id="template-source" className="form-select customer-edit-control" value={form.firstSuggestHair} onChange={(event) => patch({ firstSuggestHair: event.target.value as CustomerFormValues['firstSuggestHair'] })}>
|
|
|
|
|
- <option value="AUTO">{pageCopy.follow.templateOptions[0]}</option>
|
|
|
|
|
- <option value="LONG">{pageCopy.follow.templateOptions[1]}</option>
|
|
|
|
|
- <option value="MEDIUM">{pageCopy.follow.templateOptions[2]}</option>
|
|
|
|
|
- <option value="SHORT">{pageCopy.follow.templateOptions[3]}</option>
|
|
|
|
|
|
|
+ <label htmlFor="follow-contact" className="customer-edit-label">{pageCopy.follow.templateEdit}</label>
|
|
|
|
|
+ <select id="follow-contact" className="form-select customer-edit-control" value={form.expectContact} onChange={(event) => patch({ expectContact: event.target.value as CustomerFormValues['expectContact'] })}>
|
|
|
|
|
+ <option value="LINE">LINE</option>
|
|
|
|
|
+ <option value="PHONE">{pageCopy.follow.contactOptions[1]}</option>
|
|
|
|
|
+ <option value="EMAIL">{pageCopy.follow.contactOptions[2]}</option>
|
|
|
|
|
+ <option value="NONE">{pageCopy.basic.contactNewOptions[3]}</option>
|
|
|
</select>
|
|
</select>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <div className="col-12">
|
|
|
|
|
+ <label htmlFor="follow-content" className="customer-edit-label">{pageCopy.follow.messageEdit}</label>
|
|
|
|
|
+ <textarea
|
|
|
|
|
+ id="follow-content"
|
|
|
|
|
+ className="form-control customer-edit-control"
|
|
|
|
|
+ rows={4}
|
|
|
|
|
+ value={form.followContent}
|
|
|
|
|
+ onChange={(event) => patch({ followContent: event.target.value })}
|
|
|
|
|
+ placeholder={pageCopy.follow.messageEdit}
|
|
|
|
|
+ ></textarea>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div className="customer-edit-actions workbench-panel border-radius-8px p-25px mt-4">
|
|
<div className="customer-edit-actions workbench-panel border-radius-8px p-25px mt-4">
|
|
|
<div>
|
|
<div>
|
|
|
- <strong>{pageCopy.submit.titleNew}</strong>
|
|
|
|
|
- <span>{pageCopy.submit.leadNew}</span>
|
|
|
|
|
|
|
+ <strong>{isEditMode ? pageCopy.submit.titleEdit : pageCopy.submit.titleNew}</strong>
|
|
|
|
|
+ <span>{isEditMode ? pageCopy.submit.leadEdit : pageCopy.submit.leadNew}</span>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="customer-edit-action-panel">
|
|
<div className="customer-edit-action-panel">
|
|
|
{error ? (
|
|
{error ? (
|
|
@@ -238,7 +265,7 @@ export function CustomerFormPage() {
|
|
|
</div>
|
|
</div>
|
|
|
) : null}
|
|
) : null}
|
|
|
<div className="customer-edit-action-buttons">
|
|
<div className="customer-edit-action-buttons">
|
|
|
- <Link to={path('/customers')} className="btn btn-large btn-rounded btn-transparent-light-gray border border-1 border-color-dark-gray fw-700">{copy.common.cancel}</Link>
|
|
|
|
|
|
|
+ <Link to={isEditMode && customerId ? path(`/customers/${customerId}`) : path('/customers')} className="btn btn-large btn-rounded btn-transparent-light-gray border border-1 border-color-dark-gray fw-700">{copy.common.cancel}</Link>
|
|
|
<button type="submit" disabled={submitting} className="btn btn-large btn-rounded btn-base-color btn-box-shadow fw-700"><i className="feather icon-feather-user-plus me-10px"></i>{modeCopy.submit}</button>
|
|
<button type="submit" disabled={submitting} className="btn btn-large btn-rounded btn-base-color btn-box-shadow fw-700"><i className="feather icon-feather-user-plus me-10px"></i>{modeCopy.submit}</button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|