Confirmations
This commit is contained in:
parent
cb67c5d93d
commit
551951827d
6 changed files with 283 additions and 25 deletions
|
|
@ -1,8 +1,197 @@
|
|||
<script lang="ts">
|
||||
import { Datatable, Search, RowsPerPage, RowCount, Pagination } from '@vincjo/datatables'
|
||||
import { Modal } from '@sveltestrap/sveltestrap';
|
||||
import { onMount } from 'svelte';
|
||||
import { TableHandler } from "@vincjo/datatables";
|
||||
import {
|
||||
Modal,
|
||||
Button,
|
||||
FormGroup,
|
||||
Label,
|
||||
Input,
|
||||
Alert,
|
||||
Icon,
|
||||
Pagination,
|
||||
PaginationItem,
|
||||
PaginationLink,
|
||||
} from "@sveltestrap/sveltestrap";
|
||||
import { onMount } from "svelte";
|
||||
import { addToast } from "$lib/components/Toast.svelte";
|
||||
import type { SavedPoint } from "$lib/types";
|
||||
import { SavedPointsStore } from "$lib/stores";
|
||||
import ConfirmationPrompt from "./ConfirmationPrompt.svelte";
|
||||
import { getSavedPoints, savePoint, updatePoint, deletePoint } from "$lib/api/points";
|
||||
|
||||
// Props
|
||||
let { isOpen = $bindable(false), onClose = () => {}, onChange = () => {}, point} = $props();
|
||||
|
||||
// Runes
|
||||
let selectedPoint = $derived<SavedPoint>(point);
|
||||
let isAlertVisible = $state(false);
|
||||
let isConfirmationVisible = $state(false);
|
||||
let alertText = $state("");
|
||||
|
||||
</script>
|
||||
$effect(() => {
|
||||
onChange();
|
||||
});
|
||||
|
||||
// Modal controls
|
||||
export function openModal() {
|
||||
isOpen = true;
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
isOpen = false;
|
||||
onClose();
|
||||
}
|
||||
|
||||
function handleDeletePoint(point: SavedPoint) {
|
||||
deletePoint(point.id)
|
||||
.then(() => {
|
||||
$SavedPointsStore = $SavedPointsStore.filter((p) => p.id !== point.id);
|
||||
SavedPointsStore.set($SavedPointsStore);
|
||||
resetForm();
|
||||
addToast({
|
||||
header: "Точка удалена",
|
||||
body: `Точка "${point.name}" успешно удалена.`,
|
||||
color: "success",
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
showAlert(`Ошибка при удалении точки: ${error.message}`);
|
||||
console.error("Ошибка при удалении точки:", error);
|
||||
});
|
||||
}
|
||||
|
||||
function handleSavePoint() {
|
||||
updatePoint(selectedPoint)
|
||||
.then((updatedPoint) => {
|
||||
$SavedPointsStore = $SavedPointsStore.map((p) => (p.id === updatedPoint.id ? updatedPoint : p));
|
||||
SavedPointsStore.set($SavedPointsStore);
|
||||
resetForm();
|
||||
addToast({
|
||||
header: "Точка обновлена",
|
||||
body: `Точка "${updatedPoint.name}" успешно обновлена.`,
|
||||
color: "success",
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
showAlert(`Ошибка при обновлении точки: ${error.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
export function showAlert(message: string) {
|
||||
isAlertVisible = true;
|
||||
alertText = message;
|
||||
}
|
||||
|
||||
export function hideAlert() {
|
||||
isAlertVisible = false;
|
||||
alertText = "";
|
||||
}
|
||||
|
||||
export function resetForm() {
|
||||
hideAlert();
|
||||
closeModal();
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal {isOpen} toggle={closeModal} size="lg" fade={false} backdrop={true} scrollable class={ isConfirmationVisible ? "modal-tinted" : ""}>
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Редактирование точки</h5>
|
||||
<button type="button" class="btn-close" onclick={closeModal} aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<h5>{"Редактирование точки"}</h5>
|
||||
<Alert
|
||||
color="danger"
|
||||
isOpen={isAlertVisible}
|
||||
toggle={() => (isAlertVisible = false)}
|
||||
fade={false}
|
||||
class="mb-2"
|
||||
>
|
||||
<Icon name="exclamation-triangle" class="me-2" />
|
||||
{alertText}
|
||||
</Alert>
|
||||
<form
|
||||
onsubmit={(e) => {
|
||||
e.preventDefault();
|
||||
handleSavePoint();
|
||||
}}
|
||||
>
|
||||
<div class="mb-2">
|
||||
<Label for="name" class="small">Название точки:</Label>
|
||||
<Input class="form-control-sm" type="text" id="name" bind:value={selectedPoint.name} required />
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<FormGroup class="flex-grow-1">
|
||||
<Label for="lat" class="small">Широта:</Label>
|
||||
<Input
|
||||
class="form-control-sm"
|
||||
type="number"
|
||||
step="any"
|
||||
id="lat"
|
||||
bind:value={selectedPoint.lat}
|
||||
required
|
||||
/>
|
||||
<span class="form-text">Градусы</span>
|
||||
</FormGroup>
|
||||
<FormGroup class="flex-grow-1">
|
||||
<Label for="lon" class="small">Долгота:</Label>
|
||||
<Input
|
||||
class="form-control-sm"
|
||||
type="number"
|
||||
step="any"
|
||||
id="lon"
|
||||
bind:value={selectedPoint.lon}
|
||||
required
|
||||
/>
|
||||
<span class="form-text">Градусы</span>
|
||||
</FormGroup>
|
||||
<FormGroup class="flex-grow-1">
|
||||
<Label for="alt" class="small">Высота:</Label>
|
||||
<Input
|
||||
class="form-control-sm"
|
||||
type="number"
|
||||
step="any"
|
||||
id="alt"
|
||||
bind:value={selectedPoint.alt}
|
||||
required
|
||||
/>
|
||||
<span class="form-text">Метры над ур. моря</span>
|
||||
</FormGroup>
|
||||
</div>
|
||||
<div class="d-grid gap-2 d-md-flex">
|
||||
<Button type="submit" color="success" size="sm">
|
||||
Обновить точку
|
||||
</Button>
|
||||
<Button size="sm" type="button" color="secondary" onclick={resetForm}>Отмена</Button>
|
||||
<span class="flex-grow-1"></span>
|
||||
<Button
|
||||
type="button"
|
||||
color="danger"
|
||||
size="sm"
|
||||
onclick={() => isConfirmationVisible = true}
|
||||
>
|
||||
Удалить точку
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<ConfirmationPrompt
|
||||
isOpen={isConfirmationVisible}
|
||||
title="Подтвердите удаление"
|
||||
confirmText="Удалить"
|
||||
cancelText="Отмена"
|
||||
confirmVariant="danger"
|
||||
onconfirm={() => {
|
||||
isConfirmationVisible = false;
|
||||
handleDeletePoint(selectedPoint);
|
||||
}}
|
||||
oncancel={() => {
|
||||
isConfirmationVisible = false;
|
||||
}}
|
||||
>
|
||||
<p>Вы уверены, что хотите удалить эту точку?</p>
|
||||
</ConfirmationPrompt>
|
||||
|
|
@ -16,16 +16,24 @@
|
|||
import { addToast } from "$lib/components/Toast.svelte";
|
||||
import type { SavedPoint } from "$lib/types";
|
||||
import { SavedPointsStore } from "$lib/stores";
|
||||
import ConfirmationPrompt from "./ConfirmationPrompt.svelte";
|
||||
import { getSavedPoints, savePoint, updatePoint, deletePoint } from "$lib/api/points";
|
||||
|
||||
// Props
|
||||
let { isOpen = $bindable(false), onClose = () => {}, onChange = () => {} } = $props();
|
||||
let {
|
||||
isOpen = $bindable(false),
|
||||
onClose = () => {},
|
||||
onChange = () => {},
|
||||
point = null,
|
||||
coordinates = { id: 0, name: "", lat: 0, lon: 0, alt: 0 },
|
||||
} = $props();
|
||||
|
||||
// Runes
|
||||
let selectedPoint = $state<SavedPoint | null>(null);
|
||||
let newPoint = $state<SavedPoint>({ id: 0, name: "", lat: 0, lon: 0, alt: 0 });
|
||||
let selectedPoint = $state<SavedPoint | null>(point);
|
||||
let newPoint = $state<SavedPoint>(coordinates as SavedPoint);
|
||||
let isEditing = $state(false);
|
||||
let isAlertVisible = $state(false);
|
||||
let isConfirmationVisible = $state(false);
|
||||
let alertText = $state("");
|
||||
|
||||
// Table handler
|
||||
|
|
@ -59,7 +67,13 @@
|
|||
isEditing = true;
|
||||
}
|
||||
|
||||
function handleDeletePoint(point: SavedPoint) {
|
||||
function confirmDeletePoint(point: SavedPoint) {
|
||||
selectedPoint = point;
|
||||
isConfirmationVisible = true;
|
||||
}
|
||||
|
||||
function handleDeletePoint(point: SavedPoint | null) {
|
||||
if (!point) return;
|
||||
deletePoint(point.id)
|
||||
.then(() => {
|
||||
$SavedPointsStore = $SavedPointsStore.filter((p) => p.id !== point.id);
|
||||
|
|
@ -129,7 +143,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Modal {isOpen} toggle={closeModal} size="lg" fade={false} backdrop={true} scrollable>
|
||||
<Modal {isOpen} toggle={closeModal} size="lg" fade={false} backdrop={true} scrollable class={isConfirmationVisible ? "modal-tinted" : ""}>
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Сохраненные точки</h5>
|
||||
<button type="button" class="btn-close" onclick={closeModal} aria-label="Close"></button>
|
||||
|
|
@ -179,7 +193,7 @@
|
|||
<Button color="primary" size="sm" onclick={() => handleEditPoint(row)}>
|
||||
<Icon name="pencil" />
|
||||
</Button>
|
||||
<Button color="danger" size="sm" onclick={() => handleDeletePoint(row)}>
|
||||
<Button color="danger" size="sm" onclick={() => confirmDeletePoint(row)}>
|
||||
<Icon name="trash" />
|
||||
</Button>
|
||||
</td>
|
||||
|
|
@ -275,3 +289,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<ConfirmationPrompt
|
||||
isOpen={isConfirmationVisible}
|
||||
title="Подтвердите удаление"
|
||||
confirmText="Удалить"
|
||||
cancelText="Отмена"
|
||||
confirmVariant="danger"
|
||||
onconfirm={() => {
|
||||
isConfirmationVisible = false;
|
||||
handleDeletePoint(selectedPoint);
|
||||
}}
|
||||
oncancel={() => {
|
||||
isConfirmationVisible = false;
|
||||
}}
|
||||
>
|
||||
<p>Вы уверены, что хотите удалить эту точку?</p>
|
||||
</ConfirmationPrompt>
|
||||
Loading…
Add table
Add a link
Reference in a new issue