162 lines
5.7 KiB
JavaScript
162 lines
5.7 KiB
JavaScript
import React, { useState } from "react";
|
||
import { supabase } from "../../supabaseClient";
|
||
import { Button } from "../UI/Button";
|
||
import { CallDateSelect, CallTimeSelect, toDateInputValue, toTimeInputValue } from "./CallDateTime";
|
||
|
||
const CalledPanel = ({ order, onUpdate }) => {
|
||
const [busy, setBusy] = useState(false);
|
||
const [editing, setEditing] = useState(false);
|
||
const [comment, setComment] = useState(order?.calledComment || order?.called_comment || "");
|
||
const [callDate, setCallDate] = useState("");
|
||
const [callTime, setCallTime] = useState("");
|
||
|
||
const isCalled = !!order?.called;
|
||
|
||
const formatCalledAt = (ts) => {
|
||
if (!ts) return "";
|
||
try {
|
||
return new Date(ts).toLocaleString("ru-RU", {
|
||
day: "2-digit",
|
||
month: "2-digit",
|
||
year: "numeric",
|
||
hour: "2-digit",
|
||
minute: "2-digit",
|
||
});
|
||
} catch {
|
||
return "";
|
||
}
|
||
};
|
||
|
||
// Open add form with date+time defaulted to NOW for fast entry.
|
||
const startAdd = () => {
|
||
const now = new Date();
|
||
setComment("");
|
||
setCallDate(toDateInputValue(now));
|
||
setCallTime(toTimeInputValue(now));
|
||
setEditing(true);
|
||
};
|
||
|
||
// Open edit form for an existing call, pre-filled from stored values (or now).
|
||
const startEdit = () => {
|
||
setComment(order?.calledComment || order?.called_comment || "");
|
||
if (order?.calledAt || order?.called_at) {
|
||
const d = new Date(order.calledAt || order.called_at);
|
||
setCallDate(toDateInputValue(d));
|
||
setCallTime(toTimeInputValue(d));
|
||
} else {
|
||
const now = new Date();
|
||
setCallDate(toDateInputValue(now));
|
||
setCallTime(toTimeInputValue(now));
|
||
}
|
||
setEditing(true);
|
||
};
|
||
|
||
const save = async (newCalled) => {
|
||
if (busy || !order?.id) return;
|
||
setBusy(true);
|
||
try {
|
||
let calledAt = null;
|
||
if (newCalled) {
|
||
if (callDate && callTime) {
|
||
calledAt = new Date(`${callDate}T${callTime}:00`).toISOString();
|
||
} else {
|
||
calledAt = new Date().toISOString();
|
||
}
|
||
}
|
||
const { error } = await supabase
|
||
.from("order_groups")
|
||
.update({
|
||
called: newCalled,
|
||
called_at: calledAt,
|
||
called_comment: newCalled ? (comment.trim() || null) : null,
|
||
})
|
||
.eq("id", order.id);
|
||
if (error) {
|
||
console.warn("[CalledPanel] update error", error);
|
||
} else {
|
||
setEditing(false);
|
||
if (onUpdate) await onUpdate();
|
||
}
|
||
} finally {
|
||
setBusy(false);
|
||
}
|
||
};
|
||
|
||
// Editing form: app-styled date/time pickers + comment + save/reset/cancel.
|
||
if (editing) {
|
||
return (
|
||
<div className="space-y-3">
|
||
<div className="flex flex-wrap gap-3">
|
||
<CallDateSelect value={callDate} onChange={setCallDate} />
|
||
<CallTimeSelect value={callTime} onChange={setCallTime} />
|
||
</div>
|
||
<div>
|
||
<label className="mb-1 block text-xs font-medium text-[var(--color-text-muted)]">Комментарий</label>
|
||
<textarea
|
||
value={comment}
|
||
onChange={(e) => setComment(e.target.value)}
|
||
placeholder="Результат звонка..."
|
||
rows={2}
|
||
className="w-full rounded-2xl border border-[var(--color-border)] bg-[var(--color-surface)] px-4 py-3 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)] focus:outline-none resize-none"
|
||
/>
|
||
</div>
|
||
<div className="flex flex-wrap gap-2">
|
||
<Button variant="primary" size="sm" onClick={() => save(true)} disabled={busy}>
|
||
{busy ? "Сохраняем..." : "Сохранить"}
|
||
</Button>
|
||
{isCalled && (
|
||
<Button variant="ghost" size="sm" onClick={() => save(false)} disabled={busy}>
|
||
Сбросить
|
||
</Button>
|
||
)}
|
||
<Button variant="secondary" size="sm" onClick={() => setEditing(false)} disabled={busy}>
|
||
Отмена
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="space-y-2">
|
||
<div className="flex flex-wrap items-center gap-2">
|
||
{isCalled ? (
|
||
<>
|
||
<Button variant="primary" size="sm" disabled>
|
||
📞 Звонили
|
||
</Button>
|
||
<Button variant="secondary" size="sm" onClick={() => save(false)} disabled={busy}>
|
||
Не звонили
|
||
</Button>
|
||
<Button variant="ghost" size="sm" onClick={startEdit} disabled={busy} title="Изменить дату или комментарий">
|
||
✎ Изменить
|
||
</Button>
|
||
{order?.calledAt || order?.called_at ? (
|
||
<span className="text-xs text-[var(--color-text-muted)]">{formatCalledAt(order.calledAt || order.called_at)}</span>
|
||
) : null}
|
||
{order?.calledComment || order?.called_comment ? (
|
||
<span className="text-xs text-[var(--color-text-muted)] italic">«{order.calledComment || order.called_comment}»</span>
|
||
) : null}
|
||
</>
|
||
) : (
|
||
<>
|
||
<Button variant="primary" size="sm" onClick={() => save(true)} disabled={busy}>
|
||
{busy ? "Сохраняем..." : "📞 Звонили"}
|
||
</Button>
|
||
<Button variant="ghost" size="sm" onClick={startAdd} disabled={busy} title="Записать дату и время звонка">
|
||
✎ Дата/комментарий
|
||
</Button>
|
||
</>
|
||
)}
|
||
</div>
|
||
{!isCalled && (
|
||
<p className="text-xs text-[var(--color-text-muted)]">
|
||
Нажмите «Звонили», чтобы отметить звонок прямо сейчас.
|
||
</p>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export { CalledPanel };
|
||
export default CalledPanel; |