|
| 1 | +"use client"; |
| 2 | + |
| 3 | +import Checkbox from "@/components/ui/checkbox"; |
| 4 | +import IconPlus from "@/components/ui/icons/plus"; |
| 5 | +import { Sector } from "@/graphql/generated"; |
| 6 | +import SectorCard from "./sector-card"; |
| 7 | +import { Fragment, useEffect, useState } from "react"; |
| 8 | +import SectorDialog from "./sector-dialog"; |
| 9 | +import DeleteSectorDialog from "./delete-sector-dialog"; |
| 10 | +import { |
| 11 | + DndContext, |
| 12 | + DragEndEvent, |
| 13 | + KeyboardSensor, |
| 14 | + PointerSensor, |
| 15 | + closestCenter, |
| 16 | + useSensor, |
| 17 | + useSensors, |
| 18 | +} from "@dnd-kit/core"; |
| 19 | +import { |
| 20 | + SortableContext, |
| 21 | + arrayMove, |
| 22 | + sortableKeyboardCoordinates, |
| 23 | +} from "@dnd-kit/sortable"; |
| 24 | +import { restrictToParentElement } from "@dnd-kit/modifiers"; |
| 25 | +import updateSectorAction from "../../server-actions/update-sector-action"; |
| 26 | +import { useRouter } from "next/navigation"; |
| 27 | + |
| 28 | +type TEditCragSectorsManyProps = { |
| 29 | + sectors: Sector[]; |
| 30 | + cragId: string; |
| 31 | +}; |
| 32 | + |
| 33 | +function EditSectorsMany({ sectors, cragId }: TEditCragSectorsManyProps) { |
| 34 | + const router = useRouter(); |
| 35 | + const [loading, setLoading] = useState(false); |
| 36 | + |
| 37 | + const [sectorDialogType, setSectorDialogType] = useState<"new" | "edit">(); |
| 38 | + const [sectorDialogIsOpen, setSectorDialogIsOpen] = useState(false); |
| 39 | + const [position, setPosition] = useState(0); |
| 40 | + const [sector, setSector] = useState<Sector>(sectors[0]); |
| 41 | + const [sortedSectors, setSortedSectors] = useState(sectors); |
| 42 | + useEffect(() => { |
| 43 | + setSortedSectors(sectors); |
| 44 | + }, [sectors]); |
| 45 | + |
| 46 | + const handleCragHasSectorsChange = () => {}; |
| 47 | + |
| 48 | + const handleAddSectorClick = (position: number) => { |
| 49 | + setSectorDialogType("new"); |
| 50 | + setPosition(position); |
| 51 | + setSectorDialogIsOpen(true); |
| 52 | + }; |
| 53 | + |
| 54 | + const handleEditSectorClick = (sector: Sector) => { |
| 55 | + setSectorDialogType("edit"); |
| 56 | + setSector(sector); |
| 57 | + setSectorDialogIsOpen(true); |
| 58 | + }; |
| 59 | + |
| 60 | + const [deleteSectorDialogIsOpen, setDeleteSectorDialogIsOpen] = |
| 61 | + useState(false); |
| 62 | + const handleDeleteSectorClick = (sector: Sector) => { |
| 63 | + setSector(sector); |
| 64 | + setDeleteSectorDialogIsOpen(true); |
| 65 | + }; |
| 66 | + |
| 67 | + const handleDragEnd = async (event: DragEndEvent) => { |
| 68 | + const { active, over } = event; |
| 69 | + |
| 70 | + if (over && active.id !== over.id) { |
| 71 | + setLoading(true); |
| 72 | + |
| 73 | + const droppedSectorIndex = sortedSectors.findIndex( |
| 74 | + (sector) => sector.id === active.id |
| 75 | + ); |
| 76 | + const targetSectorIndex = sortedSectors.findIndex( |
| 77 | + (sector) => sector.id === over.id |
| 78 | + ); |
| 79 | + |
| 80 | + const newSortedSectors = arrayMove( |
| 81 | + sortedSectors, |
| 82 | + droppedSectorIndex, |
| 83 | + targetSectorIndex |
| 84 | + ); |
| 85 | + |
| 86 | + setSortedSectors(newSortedSectors); |
| 87 | + |
| 88 | + const updatedSectorData = { |
| 89 | + id: sortedSectors[droppedSectorIndex].id, |
| 90 | + position: |
| 91 | + droppedSectorIndex > targetSectorIndex |
| 92 | + ? sortedSectors[targetSectorIndex].position |
| 93 | + : sortedSectors[targetSectorIndex].position + 1, |
| 94 | + }; |
| 95 | + |
| 96 | + await updateSectorAction(updatedSectorData); |
| 97 | + router.refresh(); |
| 98 | + setLoading(false); |
| 99 | + } |
| 100 | + }; |
| 101 | + |
| 102 | + const sensors = useSensors( |
| 103 | + useSensor(PointerSensor), |
| 104 | + useSensor(KeyboardSensor, { |
| 105 | + coordinateGetter: sortableKeyboardCoordinates, |
| 106 | + }) |
| 107 | + ); |
| 108 | + |
| 109 | + return ( |
| 110 | + <> |
| 111 | + <Checkbox |
| 112 | + label="Plezališče ima več sektorjev" |
| 113 | + checked={true} |
| 114 | + disabled={loading} |
| 115 | + onChange={handleCragHasSectorsChange} |
| 116 | + /> |
| 117 | + |
| 118 | + <div className="h-18 flex items-stretch mt-5"> |
| 119 | + <button |
| 120 | + disabled={loading} |
| 121 | + className={`w-full flex justify-end items-center border border-dashed rounded-lg px-4 outline-none focus-visible:ring focus-visible:ring-blue-100 ${loading ? "text-neutral-400 border-neutral-300" : "text-neutral-500 hover:border-neutral-500 hover:text-neutral-600 active:text-neutral-700 active:border-neutral-600 border-neutral-400"}`} |
| 122 | + onClick={() => handleAddSectorClick(0)} |
| 123 | + > |
| 124 | + <span className="mr-2">dodaj sektor na začetek</span> |
| 125 | + <IconPlus /> |
| 126 | + </button> |
| 127 | + </div> |
| 128 | + |
| 129 | + <DndContext |
| 130 | + onDragEnd={handleDragEnd} |
| 131 | + collisionDetection={closestCenter} |
| 132 | + modifiers={[restrictToParentElement]} |
| 133 | + sensors={sensors} |
| 134 | + id="sort-sectors-dnd-context-id" |
| 135 | + > |
| 136 | + <SortableContext items={sortedSectors}> |
| 137 | + <div> |
| 138 | + {/* Dep: sector.label is deprecated. remove after api migrates it to name */} |
| 139 | + {sortedSectors.map((sector) => ( |
| 140 | + <Fragment key={sector.id}> |
| 141 | + <SectorCard |
| 142 | + id={sector.id} |
| 143 | + name={`${sector.label} - ${sector.name}`} |
| 144 | + disabled={loading} |
| 145 | + onEditClick={() => handleEditSectorClick(sector)} |
| 146 | + onAddClick={() => handleAddSectorClick(sector.position + 1)} |
| 147 | + onDeleteClick={() => handleDeleteSectorClick(sector)} |
| 148 | + /> |
| 149 | + </Fragment> |
| 150 | + ))} |
| 151 | + </div> |
| 152 | + </SortableContext> |
| 153 | + </DndContext> |
| 154 | + |
| 155 | + {sectorDialogType === "new" ? ( |
| 156 | + <SectorDialog |
| 157 | + formType="new" |
| 158 | + isOpen={sectorDialogIsOpen} |
| 159 | + setIsOpen={setSectorDialogIsOpen} |
| 160 | + position={position} |
| 161 | + cragId={cragId} |
| 162 | + /> |
| 163 | + ) : ( |
| 164 | + <SectorDialog |
| 165 | + formType="edit" |
| 166 | + isOpen={sectorDialogIsOpen} |
| 167 | + setIsOpen={setSectorDialogIsOpen} |
| 168 | + sector={sector} |
| 169 | + /> |
| 170 | + )} |
| 171 | + |
| 172 | + <DeleteSectorDialog |
| 173 | + isOpen={deleteSectorDialogIsOpen} |
| 174 | + setIsOpen={setDeleteSectorDialogIsOpen} |
| 175 | + sector={sector} |
| 176 | + /> |
| 177 | + </> |
| 178 | + ); |
| 179 | +} |
| 180 | + |
| 181 | +export default EditSectorsMany; |
0 commit comments