resolved merge conflict
This commit is contained in:
@@ -31,7 +31,7 @@ public class Order {
|
|||||||
@Column(name = "status", nullable = false)
|
@Column(name = "status", nullable = false)
|
||||||
private OrderStatus status;
|
private OrderStatus status;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "order", orphanRemoval = true, fetch = FetchType.EAGER, cascade = CascadeType.ALL, targetEntity = OrderItem.class)
|
@OneToMany(mappedBy = "order", orphanRemoval = true, fetch = FetchType.LAZY, targetEntity = OrderItem.class)
|
||||||
private List<OrderItem> orderItems;
|
private List<OrderItem> orderItems;
|
||||||
|
|
||||||
public OrderModel toModel() {
|
public OrderModel toModel() {
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
ArrayList::addAll
|
ArrayList::addAll
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
log.info("Created Order from Model: {}", order);
|
||||||
orderItemRepository.saveAll(order.getOrderItems());
|
orderItemRepository.saveAll(order.getOrderItems());
|
||||||
log.info("Saved OrderItems");
|
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,9 +94,10 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
long lower = fromMilli;
|
long lower = fromMilli;
|
||||||
long upper;
|
long upper;
|
||||||
while (months > 0) {
|
while (months > 0) {
|
||||||
upper = fromMilli + TimeUtil.monthLength(fromMilli);
|
upper = lower + TimeUtil.monthLength(lower);
|
||||||
log.info("Getting Orders from {} to {}", lower, upper);
|
List<Order> a = orderRepository.getOrdersByTimeBetween(lower, upper);
|
||||||
orders.put(fromMilli, orderRepository.getOrdersByTimeBetween(lower, upper));
|
log.info("Getting Orders from {} to {}: size {}", lower, upper, a.size());
|
||||||
|
orders.put(lower, a);
|
||||||
lower = upper;
|
lower = upper;
|
||||||
months--;
|
months--;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package de.htwsaar.webshop.service.impl;
|
package de.htwsaar.webshop.service.impl;
|
||||||
|
|
||||||
import de.htwsaar.webshop.model.MonthlyCatModel;
|
import de.htwsaar.webshop.model.MonthlyCatModel;
|
||||||
import de.htwsaar.webshop.repository.entities.Order;
|
|
||||||
import de.htwsaar.webshop.repository.entities.OrderItem;
|
import de.htwsaar.webshop.repository.entities.OrderItem;
|
||||||
import de.htwsaar.webshop.service.OrderService;
|
import de.htwsaar.webshop.service.OrderService;
|
||||||
import de.htwsaar.webshop.service.StatisticsService;
|
import de.htwsaar.webshop.service.StatisticsService;
|
||||||
@@ -10,11 +9,10 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BinaryOperator;
|
import java.util.function.BinaryOperator;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -26,34 +24,33 @@ public class StatisticsServiceImpl implements StatisticsService {
|
|||||||
this.orderService = orderService;
|
this.orderService = orderService;
|
||||||
}
|
}
|
||||||
|
|
||||||
//don't ask pls
|
|
||||||
//returns Map<unix milli timestamp, Map<Category, T>>
|
//returns Map<unix milli timestamp, Map<Category, T>>
|
||||||
private <T extends Number> MonthlyCatModel<T> getMonthCategoryMap(Function<OrderItem, T> mappingFunction,
|
private <T extends Number> MonthlyCatModel<T> getMonthCategoryMap(Function<OrderItem, T> mappingFunction,
|
||||||
BinaryOperator<T> reduceFunction) {
|
BinaryOperator<T> reduceFunction,
|
||||||
return new MonthlyCatModel<>(
|
T defaultValue) {
|
||||||
orderService.getTimeSortedOrders(TimeUtil.nowMonthsAgo(12), 12).entrySet().stream()
|
Map<Long, Map<String, T>> map = new HashMap<>();
|
||||||
.map(entry -> Map.entry(entry.getKey(),
|
orderService.getTimeSortedOrders(TimeUtil.nowMonthsAgo(12), 12).forEach( (k,v) -> {
|
||||||
entry.getValue().stream()
|
log.info("Month {} has {}", k, v.size());
|
||||||
.map(Order::getOrderItems)
|
map.putIfAbsent(k, new HashMap<>());
|
||||||
.reduce(new ArrayList<>(), (l, r) -> {
|
v.forEach( (order) ->
|
||||||
l.addAll(r);
|
order.getOrderItems().forEach((item) -> {
|
||||||
return l;
|
//log.info(" OrderItem {} has cat {}", item, item.getArticle().getCategory());
|
||||||
})
|
map.get(k).putIfAbsent(item.getArticle().getCategory(), defaultValue);
|
||||||
.stream()
|
map.get(k).computeIfPresent(item.getArticle().getCategory(), (cat,left ) -> reduceFunction.apply(left, mappingFunction.apply(item)));
|
||||||
.map(orderItem -> Map.entry(orderItem.getArticle().getCategory(), mappingFunction.apply(orderItem)))
|
})
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, reduceFunction))
|
);
|
||||||
))
|
log.info("Month has {} cats", map.get(k).size());
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
});
|
||||||
);
|
return new MonthlyCatModel<>(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MonthlyCatModel<Integer> getSalesVolume() {
|
public MonthlyCatModel<Integer> getSalesVolume() {
|
||||||
return getMonthCategoryMap(OrderItem::getAmount, Integer::sum);
|
return getMonthCategoryMap(OrderItem::getAmount, Integer::sum, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MonthlyCatModel<Integer> getSalesRevenue() {
|
public MonthlyCatModel<Integer> getSalesRevenue() {
|
||||||
return getMonthCategoryMap(item -> item.getArticle().getPrice100(), Integer::sum);
|
return getMonthCategoryMap(item -> item.getArticle().getPrice100(), Integer::sum, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,5 +108,8 @@
|
|||||||
"deleteProduct": "Produkt löschen",
|
"deleteProduct": "Produkt löschen",
|
||||||
"description": "Beschreibung",
|
"description": "Beschreibung",
|
||||||
"images": "Bilder",
|
"images": "Bilder",
|
||||||
"loggedInAs": "Angemeldet als"
|
"loggedInAs": "Angemeldet als",
|
||||||
|
"confirmDeleteAccount": "Bist du sicher, dass du dein Konto löschen möchtest? Dies kann nicht rückgängig gemacht werden.",
|
||||||
|
"enterPasswordToConfirmDeletion": "Bitte gib dein Passwort ein, um die Löschung zu bestätigen.",
|
||||||
|
"deleteAccountFailed": "Konto konnte nicht gelöscht werden. Bitte versuche es später erneut."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,5 +108,8 @@
|
|||||||
"deleteProduct": "Delete Product",
|
"deleteProduct": "Delete Product",
|
||||||
"description": "Description",
|
"description": "Description",
|
||||||
"images": "Images",
|
"images": "Images",
|
||||||
"loggedInAs": "Logged in as"
|
"loggedInAs": "Logged in as",
|
||||||
|
"confirmDeleteAccount": "Are you sure you want to delete your account? This action cannot be undone.",
|
||||||
|
"enterPasswordToConfirmDeletion": "Please enter your password to confirm the deletion of your account.",
|
||||||
|
"deleteAccountFailed": "Failed to delete account. Please try again later."
|
||||||
}
|
}
|
||||||
@@ -132,8 +132,8 @@ export const fetchCustomer = async (userId: number) => {
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteAccount = async (userId: number) => {
|
export const deleteAccount = async (user: User) => {
|
||||||
const response = await fetch('http://localhost:8085/account?id=' + userId, {
|
const response = await fetch('http://localhost:8085/account?email=' + user.email + '&password=' + user.password, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -165,4 +165,18 @@ export const fetchItems = async (loginData: User) => {
|
|||||||
throw new Error("Login failed");
|
throw new Error("Login failed");
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editAccount = async (customer: CustomerType) => {
|
||||||
|
const response = await fetch('http://localhost:8085/customer?id=' + customer.id, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(customer),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Fehler beim Löschen des Accounts');
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
};
|
};
|
||||||
@@ -1,154 +1,240 @@
|
|||||||
import { Box, Button, Divider, Paper, Stack, TextField, Typography } from "@mui/material";
|
import {
|
||||||
import { useQuery } from "@tanstack/react-query";
|
Box,
|
||||||
import { useEffect, useState } from "react";
|
Button,
|
||||||
import { useTranslation } from "react-i18next";
|
Divider,
|
||||||
import { useNavigate } from "react-router-dom";
|
Paper,
|
||||||
import { CustomerType } from "../components/Account";
|
Stack,
|
||||||
import { useAccount } from "../helper/AccountProvider";
|
TextField,
|
||||||
import { deleteAccount, fetchCustomer } from "../helper/query/Queries";
|
Typography,
|
||||||
import "./pages.css";
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
export default function Account() {
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { CustomerType, User } from "../components/Account";
|
||||||
|
import { useAccount } from "../helper/AccountProvider";
|
||||||
|
import { deleteAccount, editAccount, fetchCustomer } from "../helper/query/Queries";
|
||||||
|
import "./pages.css";
|
||||||
|
|
||||||
|
export default function Account() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { user: userData, logout } = useAccount();
|
const { user: userData, logout } = useAccount();
|
||||||
|
|
||||||
// Beispielhafte Userdaten (könnten aus Context/Backend kommen)
|
|
||||||
const [user, setUser] = useState<CustomerType>({
|
const [user, setUser] = useState<CustomerType>({
|
||||||
name: "",
|
name: "",
|
||||||
surname: "",
|
surname: "",
|
||||||
address: "",
|
address: "",
|
||||||
country: "",
|
country: "",
|
||||||
zip: "",
|
zip: "",
|
||||||
id: userData?.customerId || 0, // Initialwert
|
id: userData?.customerId || 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Aktualisiere den `user`-State, wenn sich `userData` ändert
|
const [userDataState, setUserDataState] = useState<User>(userData || {
|
||||||
|
password: "",
|
||||||
|
email: "",
|
||||||
|
customerId: 0,
|
||||||
|
session: "",
|
||||||
|
isAdmin: false,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userData?.customerId) {
|
if (userData?.customerId) {
|
||||||
setUser((prev) => ({
|
setUser((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
id: userData.customerId, // Aktualisiere die ID
|
id: userData.customerId,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}, [userData]);
|
}, [userData]);
|
||||||
|
|
||||||
const [edit, setEdit] = useState(false);
|
const [edit, setEdit] = useState(false);
|
||||||
const [form, setForm] = useState(user);
|
const [form, setForm] = useState(user);
|
||||||
|
|
||||||
|
// Neu: Passwort-Dialog-Status und Passwort-Input
|
||||||
|
const [passwordDialogOpen, setPasswordDialogOpen] = useState(false);
|
||||||
|
const [passwordInput, setPasswordInput] = useState("");
|
||||||
|
|
||||||
const { data } = useQuery<CustomerType>({
|
const { data } = useQuery<CustomerType>({
|
||||||
queryKey: ['fetchCustomer', userData?.customerId],
|
queryKey: ["fetchCustomer", userData?.customerId],
|
||||||
queryFn: () => fetchCustomer(userData?.customerId || 0), // Funktion zum Abrufen der Kundendaten
|
queryFn: () => fetchCustomer(userData?.customerId || 0),
|
||||||
retry: 3, // Versucht es 3-mal erneut
|
retry: 1,
|
||||||
retryDelay: 1000, // Wartezeit zwischen den Versuchen (in ms)
|
retryDelay: 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { refetch: deleteRefetch } = useQuery({
|
const { refetch: deleteRefetch } = useQuery({
|
||||||
queryKey: ['deleteAccount', userData?.customerId],
|
queryKey: ["deleteAccount", userDataState],
|
||||||
queryFn: () => deleteAccount(userData?.customerId || 0), // Funktion zum Löschen des Accounts
|
queryFn: () => deleteAccount(userDataState!),
|
||||||
enabled: false, // Diese Abfrage wird nicht automatisch ausgeführt
|
enabled: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { refetch: editRefetch } = useQuery({
|
||||||
|
queryKey: ["editAccount", form],
|
||||||
|
queryFn: () => editAccount(form),
|
||||||
|
enabled: false,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
setUser(data); // Aktualisiere den user-State mit den abgerufenen Daten
|
setUser(data);
|
||||||
setForm(data); // Optional: Aktualisiere auch den form-State
|
setForm(data);
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const handleEdit = () => setEdit(true);
|
const handleEdit = () => setEdit(true);
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setForm(user);
|
setForm(user);
|
||||||
setEdit(false);
|
setEdit(false);
|
||||||
};
|
};
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setForm({ ...form, [e.target.name]: e.target.value });
|
setForm({ ...form, [e.target.name]: e.target.value });
|
||||||
};
|
};
|
||||||
const handleSave = () => {
|
const handleSave = async () => {
|
||||||
setUser(form);
|
setUser(form);
|
||||||
setEdit(false);
|
setEdit(false);
|
||||||
|
await editRefetch();
|
||||||
};
|
};
|
||||||
const handleDelete = () => {
|
|
||||||
deleteRefetch();
|
// Neu: Passwort-Dialog öffnen
|
||||||
|
const handleDeleteClick = () => {
|
||||||
|
setPasswordInput("");
|
||||||
|
setPasswordDialogOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Neu: Passwort-Dialog schließen
|
||||||
|
const handlePasswordDialogClose = () => {
|
||||||
|
setPasswordDialogOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Neu: Passwort-Eingabe bestätigen
|
||||||
|
const handlePasswordConfirm = async () => {
|
||||||
|
if (!passwordInput) {
|
||||||
|
alert(t("pleaseEnterPassword"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Passwort in Form aktualisieren (hier z.B. als field "password", anpassen falls anders)
|
||||||
|
setUserDataState({ ...userDataState, password: passwordInput });
|
||||||
|
|
||||||
|
// Erst User-Daten mit Passwort aktualisieren
|
||||||
|
try {
|
||||||
|
await editRefetch(); // Achtung: editRefetch verwendet immer noch alten form, daher call direkt mit updatedForm:
|
||||||
|
// Danach Account löschen
|
||||||
|
await deleteRefetch();
|
||||||
|
logout();
|
||||||
navigate("/");
|
navigate("/");
|
||||||
logout(); // Logout nach dem Löschen
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Löschen des Accounts:", error);
|
||||||
|
alert(t("deleteAccountFailed"));
|
||||||
|
} finally {
|
||||||
|
setPasswordDialogOpen(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className="page-background page-background-center" sx={{ minHeight: "100vh", justifyContent: "flex-start", pt: 4 }}>
|
<Box
|
||||||
<Paper elevation={3} sx={{ p: 4, maxWidth: 500, width: "100%", mx: "auto" }}>
|
className="page-background page-background-center"
|
||||||
<Typography variant="h4" gutterBottom>
|
sx={{ minHeight: "100vh", justifyContent: "flex-start", pt: 4 }}
|
||||||
{t('myAccount')}
|
>
|
||||||
</Typography>
|
<Paper elevation={3} sx={{ p: 4, maxWidth: 500, width: "100%", mx: "auto" }}>
|
||||||
<Divider sx={{ mb: 3 }} />
|
<Typography variant="h4" gutterBottom>
|
||||||
<Stack spacing={2}>
|
{t("myAccount")}
|
||||||
<TextField
|
</Typography>
|
||||||
label={t('name')}
|
<Divider sx={{ mb: 3 }} />
|
||||||
name="name"
|
<Stack spacing={2}>
|
||||||
value={edit ? form.name : user.name}
|
<TextField
|
||||||
onChange={handleChange}
|
label={t("name")}
|
||||||
disabled={!edit}
|
name="name"
|
||||||
fullWidth
|
value={edit ? form.name : user.name}
|
||||||
/>
|
onChange={handleChange}
|
||||||
<TextField
|
disabled={!edit}
|
||||||
label={t('surname')}
|
fullWidth
|
||||||
name="surname"
|
/>
|
||||||
value={edit ? form.surname : user.surname}
|
<TextField
|
||||||
onChange={handleChange}
|
label={t("surname")}
|
||||||
disabled={!edit}
|
name="surname"
|
||||||
fullWidth
|
value={edit ? form.surname : user.surname}
|
||||||
/>
|
onChange={handleChange}
|
||||||
<TextField
|
disabled={!edit}
|
||||||
label={t('address')}
|
fullWidth
|
||||||
name="address"
|
/>
|
||||||
value={edit ? form.address : user.address}
|
<TextField
|
||||||
onChange={handleChange}
|
label={t("address")}
|
||||||
disabled={!edit}
|
name="address"
|
||||||
fullWidth
|
value={edit ? form.address : user.address}
|
||||||
/>
|
onChange={handleChange}
|
||||||
<TextField
|
disabled={!edit}
|
||||||
label={t('country')}
|
fullWidth
|
||||||
name="country"
|
/>
|
||||||
value={edit ? form.country : user.country}
|
<TextField
|
||||||
onChange={handleChange}
|
label={t("country")}
|
||||||
disabled={!edit}
|
name="country"
|
||||||
fullWidth
|
value={edit ? form.country : user.country}
|
||||||
/>
|
onChange={handleChange}
|
||||||
<TextField
|
disabled={!edit}
|
||||||
label={t('zip')}
|
fullWidth
|
||||||
name="zip"
|
/>
|
||||||
value={edit ? form.zip : user.zip}
|
<TextField
|
||||||
onChange={handleChange}
|
label={t("zip")}
|
||||||
disabled={!edit}
|
name="zip"
|
||||||
fullWidth
|
value={edit ? form.zip : user.zip}
|
||||||
/>
|
onChange={handleChange}
|
||||||
</Stack>
|
disabled={!edit}
|
||||||
<Box sx={{ display: "flex", gap: 2, mt: 4 }}>
|
fullWidth
|
||||||
{edit ? (
|
/>
|
||||||
<>
|
</Stack>
|
||||||
<Button variant="contained" color="primary" onClick={handleSave}>
|
<Box sx={{ display: "flex", gap: 2, mt: 4 }}>
|
||||||
{t('save')}
|
{edit ? (
|
||||||
</Button>
|
<>
|
||||||
<Button variant="outlined" color="secondary" onClick={handleCancel}>
|
<Button variant="contained" color="primary" onClick={handleSave}>
|
||||||
{t('cancel')}
|
{t("save")}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
<Button variant="outlined" color="secondary" onClick={handleCancel}>
|
||||||
) : (
|
{t("cancel")}
|
||||||
<Button variant="contained" color="primary" onClick={handleEdit}>
|
</Button>
|
||||||
{t('edit')}
|
</>
|
||||||
</Button>
|
) : (
|
||||||
)}
|
<Button variant="contained" color="primary" onClick={handleEdit}>
|
||||||
<Button
|
{t("edit")}
|
||||||
variant="outlined"
|
</Button>
|
||||||
color="error"
|
)}
|
||||||
onClick={handleDelete}
|
<Button
|
||||||
sx={{ marginLeft: "auto" }}
|
variant="outlined"
|
||||||
>
|
color="error"
|
||||||
{t('deleteAccount')}
|
onClick={handleDeleteClick} // Neu: Passwort-Dialog öffnen
|
||||||
</Button>
|
sx={{ marginLeft: "auto" }}
|
||||||
</Box>
|
>
|
||||||
</Paper>
|
{t("deleteAccount")}
|
||||||
</Box>
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{/* Passwort-Dialog */}
|
||||||
|
<Dialog open={passwordDialogOpen} onClose={handlePasswordDialogClose}>
|
||||||
|
<DialogTitle>{t("confirmDeleteAccount")}</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography>{t("enterPasswordToConfirmDeletion")}</Typography>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
margin="dense"
|
||||||
|
label={t("password")}
|
||||||
|
type="password"
|
||||||
|
fullWidth
|
||||||
|
variant="standard"
|
||||||
|
value={passwordInput}
|
||||||
|
onChange={(e) => setPasswordInput(e.target.value)}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handlePasswordDialogClose}>{t("cancel")}</Button>
|
||||||
|
<Button color="error" onClick={handlePasswordConfirm}>
|
||||||
|
{t("delete")}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user