[CLAUDE] FE-User+FE-Admin: Edit + Xóa, chỉ hiện khi DangSoanThao
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m45s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m45s
User feedback: 2 button trên row Panel 1 phải là Edit + Xóa, và CHỈ hoạt động trong trạng thái nhập liệu/điều chỉnh (Phase = DangSoanThao). ## Thay đổi - ✏ Pencil icon thay ExternalLink — hành động Edit (select Panel 2 form) - 🗑 Trash2 — Xóa (giữ nguyên) - Cả 2 button bọc trong `c.phase === DangSoanThao` conditional → Phase khác (DangGopY, DangDamPhan, ...) → ẩn cả 2 - Lý do: BE chỉ cho update + delete khi Phase=DangSoanThao (UpdateContractDraftCommand + DeleteContractCommand throw Conflict- Exception nếu khác) ## UX - Phase=DangSoanThao: hover row → 2 button fade in - Phase khác: chỉ row click select Panel 2 (form sẽ render read-only + banner amber "HĐ đã chuyển khỏi Đang soạn thảo") Build: tsc + vite pass cả 2 app Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -12,8 +12,8 @@
|
||||
// hiển thị Chi tiết section.
|
||||
import { useState, useMemo, type FormEvent, useEffect } from 'react'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { FileText, Plus, Search, Save, ExternalLink, Trash2 } from 'lucide-react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
import { FileText, Plus, Search, Save, Pencil, Trash2 } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { ContractDetailsTab } from '@/components/contracts/ContractDetailsTab'
|
||||
import { PhaseBadge } from '@/components/PhaseBadge'
|
||||
@ -39,7 +39,6 @@ import {
|
||||
const fmtMoney = (v: number) => v.toLocaleString('vi-VN')
|
||||
|
||||
export function ContractCreatePage() {
|
||||
const navigate = useNavigate()
|
||||
const qc = useQueryClient()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const typeFilter = searchParams.get('type') ? Number(searchParams.get('type')) : 2
|
||||
@ -187,14 +186,17 @@ export function ContractCreatePage() {
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* Action buttons — hover-show, sibling không nested để click không trigger row select */}
|
||||
{/* Action buttons — Edit + Xóa, CHỈ hiện khi Phase = DangSoanThao
|
||||
(state nhập liệu / điều chỉnh). Sau khi nộp lên Góp ý → ẩn cả 2.
|
||||
Sibling không nested để click không trigger row select. */}
|
||||
{c.phase === ContractPhase.DangSoanThao && (
|
||||
<div className="absolute right-2 top-2 z-10 flex gap-0.5 opacity-0 transition group-hover:opacity-100">
|
||||
<button
|
||||
onClick={() => navigate(`/contracts/${c.id}`)}
|
||||
title="Mở chi tiết (fullpage)"
|
||||
onClick={() => selectContract(c.id)}
|
||||
title="Chỉnh sửa HĐ"
|
||||
className="rounded p-1 text-slate-500 hover:bg-white hover:text-brand-600 hover:shadow-sm"
|
||||
>
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
@ -209,6 +211,7 @@ export function ContractCreatePage() {
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@ -12,8 +12,8 @@
|
||||
// hiển thị Chi tiết section.
|
||||
import { useState, useMemo, type FormEvent, useEffect } from 'react'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { FileText, Plus, Search, Save, ExternalLink, Trash2 } from 'lucide-react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
import { FileText, Plus, Search, Save, Pencil, Trash2 } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { ContractDetailsTab } from '@/components/contracts/ContractDetailsTab'
|
||||
import { PhaseBadge } from '@/components/PhaseBadge'
|
||||
@ -39,7 +39,6 @@ import {
|
||||
const fmtMoney = (v: number) => v.toLocaleString('vi-VN')
|
||||
|
||||
export function ContractCreatePage() {
|
||||
const navigate = useNavigate()
|
||||
const qc = useQueryClient()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const typeFilter = searchParams.get('type') ? Number(searchParams.get('type')) : 2
|
||||
@ -187,14 +186,17 @@ export function ContractCreatePage() {
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* Action buttons — hover-show, sibling không nested để click không trigger row select */}
|
||||
{/* Action buttons — Edit + Xóa, CHỈ hiện khi Phase = DangSoanThao
|
||||
(state nhập liệu / điều chỉnh). Sau khi nộp lên Góp ý → ẩn cả 2.
|
||||
Sibling không nested để click không trigger row select. */}
|
||||
{c.phase === ContractPhase.DangSoanThao && (
|
||||
<div className="absolute right-2 top-2 z-10 flex gap-0.5 opacity-0 transition group-hover:opacity-100">
|
||||
<button
|
||||
onClick={() => navigate(`/contracts/${c.id}`)}
|
||||
title="Mở chi tiết (fullpage)"
|
||||
onClick={() => selectContract(c.id)}
|
||||
title="Chỉnh sửa HĐ"
|
||||
className="rounded p-1 text-slate-500 hover:bg-white hover:text-brand-600 hover:shadow-sm"
|
||||
>
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
@ -209,6 +211,7 @@ export function ContractCreatePage() {
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user