handle onleave new user, adjust background jobs

This commit is contained in:
dbdbd9 2025-06-24 15:39:11 +07:00
parent c2c9322e7d
commit fb6c58f1c0
13 changed files with 333 additions and 65 deletions

View File

@ -524,8 +524,8 @@ class TicketController extends Controller
$onleave_days_will_use = 0; // Ngày phép sẽ dùng trong tháng $onleave_days_will_use = 0; // Ngày phép sẽ dùng trong tháng
$nopay_days_will_use = 0; // Ngày ko phép sẽ dùng trong tháng $nopay_days_will_use = 0; // Ngày ko phép sẽ dùng trong tháng
// Ngày phép còn lại <= 0 (Hết phép) // Ngày phép còn lại <= 0 (Hết phép) hoặc là nhân viên chưa chính thức
if ($remainingOnleaveDaysInMonth <= 0) { if ($remainingOnleaveDaysInMonth <= 0 || !$user->is_permanent) {
$hasInsufficientDays = true; $hasInsufficientDays = true;
$month_data_status = 'no_days_left'; $month_data_status = 'no_days_left';
$onleave_days_will_use = 0; $onleave_days_will_use = 0;
@ -709,20 +709,35 @@ class TicketController extends Controller
$totalAllocated = 0; $totalAllocated = 0;
if ($leaveDaysInfo) { if ($leaveDaysInfo) {
// if ($leaveDaysInfo->ld_day_total > $month) { $currentMonth = Carbon::now()->month;
// $totalAllocated = $month;
// } else {
$totalAllocated = $leaveDaysInfo->ld_day_total; $totalAllocated = $leaveDaysInfo->ld_day_total;
// }
// Nếu là duyệt ticket thì sẽ cộng thêm số ngày phép còn lại của tháng hiện tại // Check có phải là nhân viên chính thức trong năm nay
// if ($isAccept) { $isProbationInYear = false;
if ($month >= $totalAllocated) { if ($user->permanent_date && $user->permanent_date !== '0000-00-00') {
$totalAllocated += $month - $totalAllocated; $permenantYear = Carbon::parse($user->permanent_date)->year;
if ($permenantYear === $year) {
$isProbationInYear = true;
}
} }
// }
// bên hàm duyệt ticket sẽ check lại để + 1 ngày trước job để đảm bảo đủ ngày phép
// Nhân viên mới
if ($isProbationInYear) {
$permanentMonth = Carbon::parse($user->permanent_date)->month;
if ($month > $currentMonth) {
$permanentCategory = Category::where('c_type', 'PERMANENT_ONLEAVE')->where('c_code', "PERMANENT")->first();
$permanentDefault = (int) $permanentCategory->c_value; // Ngày phép khi thành nv chính thức
$totalAllocated = $month - ($permanentMonth - $permanentDefault);
}
}
// Nhân viên cũ
else {
if ($month > $currentMonth) {
$totalAllocated = $month;
}
}
} else { } else {
Log::warning("No LeaveDays record found for user ID: {$user->id}, year: {$year}. Assuming 0 allocated days."); Log::warning("No LeaveDays record found for user ID: {$user->id}, year: {$year}. Assuming 0 allocated days.");
} }

View File

@ -3,13 +3,15 @@
namespace Modules\Auth\app\Http\Controllers; namespace Modules\Auth\app\Http\Controllers;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\LeaveDays;
use App\Traits\IsAPI; use App\Traits\IsAPI;
use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Modules\Auth\app\Models\User; use Modules\Auth\app\Models\User;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Modules\Admin\app\Models\Category;
use SimpleSoftwareIO\QrCode\Facades\QrCode; use SimpleSoftwareIO\QrCode\Facades\QrCode;
class UserController extends Controller class UserController extends Controller
@ -34,9 +36,36 @@ class UserController extends Controller
]); ]);
if ($request->has('id')) { if ($request->has('id')) {
$payload = $request->only(['name', 'email', 'permission']); $payload = $request->only(['name', 'email', 'permission', 'is_permanent']);
$user = User::find($request->id); $user = User::find($request->id);
// Không cho chuyển từ chính thức thành lại thử việc
if (!$request->is_permanent && $user->is_permanent) {
return response()->json(['status' => false, 'message' => 'You cannot change an employee from permanent to probationary.']);
}
// Thêm ngày phép khi thành nhân viên chính thức
if ($request->is_permanent && !$user->is_permanent) {
$userLeaveDay = LeaveDays::where('ld_user_id', $user->id)
->where('ld_year', Carbon::now()->year)
->first();
if ($userLeaveDay) {
$permanentCategory = Category::where('c_type', 'PERMANENT_ONLEAVE')->where('c_code', "PERMANENT")->first();
$permanentDefault = (int) $permanentCategory->c_value; // Ngày phép khi thành nv chính thức
$userLeaveDay->ld_day_total = $permanentDefault;
$newNote = "Cộng ngày phép cho nhân viên chính thức"; // Thêm ghi chú
if (!empty($userLeaveDay->ld_note)) {
$userLeaveDay->ld_note = $userLeaveDay->ld_note . "\n" . $newNote;
} else {
$userLeaveDay->ld_note = $newNote;
}
$userLeaveDay->save();
}
}
$payload['permanent_date'] = Carbon::now()->toDateString();
$user->update($payload); $user->update($payload);
return response()->json(['data' => $user, 'status' => true, 'message' => 'Update successful']); return response()->json(['data' => $user, 'status' => true, 'message' => 'Update successful']);
} else { } else {
@ -44,7 +73,19 @@ class UserController extends Controller
'name' => $request->name, 'name' => $request->name,
'email' => $request->email, 'email' => $request->email,
'password' => bcrypt('Work@1234'), 'password' => bcrypt('Work@1234'),
'permission' => $request->permission 'permission' => $request->permission,
'is_permanent' => false
]);
// Khởi tạo LeaveDays cho nhân viên mới
LeaveDays::insert([
'ld_user_id' => $user->id,
'ld_day_total' => 0,
'ld_year' => Carbon::now()->year,
'ld_additional_day' => 0,
'ld_note' => '',
'created_at' => now(),
'updated_at' => now(),
]); ]);
$user_res = [ $user_res = [
@ -98,8 +139,6 @@ class UserController extends Controller
return response()->json(['data' => ['user' => $user_res, 'gitea' => "dev", 'zulip' => "dev"], 'status' => true, 'message' => 'Create successful']); return response()->json(['data' => ['user' => $user_res, 'gitea' => "dev", 'zulip' => "dev"], 'status' => true, 'message' => 'Create successful']);
} }
} }
return response()->json(['status' => false, 'message' => 'Process fail']);
} }
public function delete(Request $request) public function delete(Request $request)

View File

@ -25,7 +25,9 @@ class User extends Authenticatable implements JWTSubject
'name', 'name',
'email', 'email',
'password', 'password',
'permission' 'permission',
'is_permanent',
'permanent_date'
]; ];
/** /**

View File

@ -25,7 +25,7 @@ class Kernel extends ConsoleKernel
// ->dailyAt('18:00'); // ->dailyAt('18:00');
// Chạy command vào ngày 31/12 lúc 23:59:59 mỗi năm // Chạy command vào ngày 31/12 lúc 23:59:59 mỗi năm
// $schedule->command('initialize:leavedays')->yearlyOn(12, 31, '23:59:59'); $schedule->command('initialize:leavedays')->yearlyOn(12, 31, '23:59:59');
$schedule->command('leave:deduct')->yearlyOn(3, 31, '23:59:59'); $schedule->command('leave:deduct')->yearlyOn(3, 31, '23:59:59');
// Chạy buổi sáng lúc 12:00 // Chạy buổi sáng lúc 12:00

View File

@ -10,6 +10,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Modules\Admin\app\Models\Category;
class AddMonthlyLeaveDays implements ShouldQueue class AddMonthlyLeaveDays implements ShouldQueue
{ {
@ -18,6 +19,8 @@ class AddMonthlyLeaveDays implements ShouldQueue
protected $month; protected $month;
protected $year; protected $year;
private const ONLEAVE_PER_MONTH = 1; // Ngày phép cộng mỗi tháng
public function __construct($month = null, $year = null) public function __construct($month = null, $year = null)
{ {
$this->month = $month ?? Carbon::now()->month; $this->month = $month ?? Carbon::now()->month;
@ -29,6 +32,11 @@ class AddMonthlyLeaveDays implements ShouldQueue
$users = User::get(); $users = User::get();
foreach ($users as $user) { foreach ($users as $user) {
// Nếu là nhân viên chưa chính thức, ko cộng phép
if (!$user->is_permanent) {
continue;
}
$leaveDay = LeaveDays::where('ld_user_id', $user->id) $leaveDay = LeaveDays::where('ld_user_id', $user->id)
->where('ld_year', $this->year) ->where('ld_year', $this->year)
->first(); ->first();
@ -46,11 +54,36 @@ class AddMonthlyLeaveDays implements ShouldQueue
]); ]);
$leaveDay->save(); $leaveDay->save();
} else { } else {
// Kiểm tra nếu số ngày phép hiện tại nhỏ hơn tháng hiện tại // Check có phải là nhân viên chính thức trong năm nay (Nhân viên mới)
if ($user->permanent_date && $user->permanent_date !== '0000-00-00') {
$permenantYear = Carbon::parse($user->permanent_date)->year;
if ($permenantYear === $this->year) {
$permanentCategory = Category::where('c_type', 'PERMANENT_ONLEAVE')->where('c_code', "PERMANENT")->first();
$permanentDefault = (int) $permanentCategory->c_value; // Ngày phép khi thành nv chính thức
$permanentMonth = Carbon::parse($user->permanent_date)->month;
if ($this->month > $leaveDay->ld_day_total - ($permanentDefault - $permanentMonth)) {
$leaveDay->ld_day_total += self::ONLEAVE_PER_MONTH;
// Xử lý ghi chú
$newNote = "Cập nhật ngày phép đến tháng " . $this->month;
if (!empty($leaveDay->ld_note)) {
// Nếu đã có ghi chú, thêm ghi chú mới vào và xuống dòng
$leaveDay->ld_note = $leaveDay->ld_note . "\n" . $newNote;
} else {
// Nếu chưa có ghi chú, gán ghi chú mới
$leaveDay->ld_note = $newNote;
}
$leaveDay->save();
}
}
}
// Kiểm tra nếu số ngày phép hiện tại nhỏ hơn tháng hiện tại (Nhân viên cũ)
if ($leaveDay->ld_day_total < $this->month) { if ($leaveDay->ld_day_total < $this->month) {
// Cập nhật số ngày phép bằng với tháng hiện tại // Cộng mỗi tháng 1 ngày phép cho nhân viên
$oldDays = $leaveDay->ld_day_total; $leaveDay->ld_day_total += self::ONLEAVE_PER_MONTH;
$leaveDay->ld_day_total = $this->month;
// Xử lý ghi chú // Xử lý ghi chú
$newNote = "Cập nhật ngày phép đến tháng " . $this->month; $newNote = "Cập nhật ngày phép đến tháng " . $this->month;

View File

@ -10,7 +10,6 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon; use Carbon\Carbon;
class DeductLeaveDays implements ShouldQueue class DeductLeaveDays implements ShouldQueue
@ -42,38 +41,19 @@ class DeductLeaveDays implements ShouldQueue
continue; continue;
} }
$totalLeaveDaysByMonth = Notes::join('categories', function ($join) { // Lấy tổng ngày nghỉ phép 3 tháng đầu trong năm
$usedOnleaveDaysTotal = Notes::join('categories', function ($join) {
$join->on('notes.n_time_type', '=', 'categories.c_code') $join->on('notes.n_time_type', '=', 'categories.c_code')
->where('categories.c_type', 'TIME_TYPE'); ->where('categories.c_type', 'TIME_TYPE');
}) })
->select( ->where('n_user_id', $user->id)
DB::raw('notes.n_user_id as n_user_id'), ->where('n_year', $this->year)
DB::raw('notes.n_year as year'), ->where('n_month', "<=", 3)
DB::raw('SUM(categories.c_value) as leave_days') ->where('n_reason', 'ONLEAVE')
) ->sum('categories.c_value');
->where('notes.n_year', $this->year)
->where('notes.n_user_id', $user->id)
->where('notes.n_reason', 'ONLEAVE')
->groupBy(DB::raw('notes.n_year'))
->first();
if ($totalLeaveDaysByMonth) { $existingData->ld_additional_day = $usedOnleaveDaysTotal ?? 0;
//Nếu ngày phép thừa năm trước chưa sử dụng hết => cập nhật lại ngày đó (Ngày tồn đọng - ngày sử dụng) $existingData->save();
if ($existingData->ld_additional_day > $totalLeaveDaysByMonth->leave_days) {
LeaveDays::where('ld_year', $this->year)
->where('ld_user_id', $user->id)
->update([
'ld_additional_day' => $totalLeaveDaysByMonth->leave_days,
]);
}
} else {
//Nếu không sử dụng ngày nghỉ còn lại ở năm rồi thì xóa => theo luật ld
LeaveDays::where('ld_year', $this->year)
->where('ld_user_id', $user->id)
->update([
'ld_additional_day' => "0",
]);
}
} }
} }
} }

View File

@ -34,7 +34,8 @@ class InitializeLeaveDays implements ShouldQueue
public function handle(): void public function handle(): void
{ {
$users = User::get(); $users = User::get();
$ld_day_total = 12; $ld_day_total = Carbon::now()->month; // Khởi tạo phép hiện có bằng tháng hiện tại
foreach ($users as $user) { foreach ($users as $user) {
// Kiểm tra xem dữ liệu của user này đã tồn tại cho năm hiện tại chưa // Kiểm tra xem dữ liệu của user này đã tồn tại cho năm hiện tại chưa
$existingData = LeaveDays::where('ld_user_id', $user->id) $existingData = LeaveDays::where('ld_user_id', $user->id)
@ -82,7 +83,7 @@ class InitializeLeaveDays implements ShouldQueue
// Tạo dữ liệu cho năm hiện tại // Tạo dữ liệu cho năm hiện tại
LeaveDays::insert([ LeaveDays::insert([
'ld_user_id' => $user->id, 'ld_user_id' => $user->id,
'ld_day_total' => $ld_day_total, 'ld_day_total' => $user->is_permanent ? $ld_day_total : 0, // Nếu là nhân viên mới, ko cấp phép
'ld_year' => $this->year, 'ld_year' => $this->year,
'ld_additional_day' => $ld_additional_day, 'ld_additional_day' => $ld_additional_day,
'ld_note' => $ld_note, 'ld_note' => $ld_note,

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_permanent')->default(true);
$table->date('permanent_date');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_permanent');
$table->dropColumn('permanent_date');
});
}
};

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::table('categories')->insert([
[
'c_code' => 'PERMANENT',
'c_name' => 'Phép cộng nhân viên chính thức',
'c_type' => 'PERMANENT_ONLEAVE',
'c_value' => 3,
'c_active' => 1,
'created_at' => now(),
'updated_at' => now(),
],
]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::table('categories')->where('c_code', 'PERMANENT')->delete();
}
};

View File

@ -654,12 +654,18 @@ const TicketsManagement = () => {
onClick={() => { onClick={() => {
setIsRefuseConfirmOpen(false) setIsRefuseConfirmOpen(false)
}} }}
disabled={disableBtn}
> >
Cancel Cancel
</Button> </Button>
<Button <Button
className={classes.deleteButton} className={classes.deleteButton}
onClick={() => handleUpdate(form.values)} onClick={async () => {
setDisableBtn(true)
await handleUpdate(form.values)
setDisableBtn(false)
}}
disabled={disableBtn}
> >
Confirm Confirm
</Button> </Button>

View File

@ -45,3 +45,37 @@
.dialogText { .dialogText {
color: light-dark(#2d353c, white); color: light-dark(#2d353c, white);
} }
/* Thêm styles cho Modal xác nhận xóa */
.deleteModal {
background-color: light-dark(white, #2d353c);
text-align: center;
border: solid 1px rgb(9, 132, 132);
}
.deleteModalTitle {
color: rgb(9, 132, 132);
font-weight: 600;
font-size: 1.2rem;
margin-bottom: 1rem;
}
.deleteModalContent {
color: light-dark(#2d353c, white);
margin-bottom: 1.5rem;
}
.deleteModalFooter {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 1rem;
}
.deleteButton {
background-color: rgb(9, 132, 132);
}
.deleteButton:hover {
background-color: rgb(9, 132, 132);
}

View File

@ -13,6 +13,7 @@ import {
Group, Group,
Modal, Modal,
MultiSelect, MultiSelect,
Switch,
Text, Text,
TextInput, TextInput,
} from '@mantine/core' } from '@mantine/core'
@ -24,28 +25,31 @@ const UsersManagement = () => {
const [users, setUsers] = useState<TUser[]>([]) const [users, setUsers] = useState<TUser[]>([])
const [action, setAction] = useState('') const [action, setAction] = useState('')
const [activeBtn, setActiveBtn] = useState(false) const [activeBtn, setActiveBtn] = useState(false)
const [item, setItem] = useState({ id: 0 }) const [item, setItem] = useState({ id: 0, is_permanent: false })
const [disableBtn, setDisableBtn] = useState(false) const [disableBtn, setDisableBtn] = useState(false)
const [info, setInfo] = useState('') const [info, setInfo] = useState('')
const [isPermanentConfirmOpen, setIsPermanentConfirmOpen] =
useState<boolean>(false)
const columns = [ const columns = [
{ {
name: 'id', name: 'id',
size: '3%', size: '5%',
header: 'ID', header: 'ID',
}, },
{ {
name: 'name', name: 'name',
size: '17%', size: '20%',
header: 'Name', header: 'Name',
}, },
{ {
name: 'email', name: 'email',
size: '26%', size: '25%',
header: 'Email', header: 'Email',
}, },
{ {
name: 'permission', name: 'permission',
size: '10%', size: '20%',
header: 'Permission', header: 'Permission',
render: (row: TUser) => { render: (row: TUser) => {
if (row.permission.includes(',')) { if (row.permission.includes(',')) {
@ -57,9 +61,21 @@ const UsersManagement = () => {
} }
}, },
}, },
{
name: 'is_permanent',
size: '20%',
header: 'Employment Type',
render: (row: TUser) => {
return row.is_permanent ? (
<Badge color="teal">Permanent</Badge>
) : (
<Badge color="violet">Probation</Badge>
)
},
},
{ {
name: '#', name: '#',
size: '5%', size: '10%',
header: 'Action', header: 'Action',
render: (row: TUser) => { render: (row: TUser) => {
return ( return (
@ -68,6 +84,8 @@ const UsersManagement = () => {
className={classes.editIcon} className={classes.editIcon}
onClick={() => { onClick={() => {
setAction('edit') setAction('edit')
setItem(row)
form.reset()
form.setValues(row) form.setValues(row)
}} }}
width={20} width={20}
@ -94,6 +112,7 @@ const UsersManagement = () => {
name: '', name: '',
email: '', email: '',
permission: '', permission: '',
is_permanent: false,
}, },
}) })
@ -128,6 +147,7 @@ const UsersManagement = () => {
const res = await update(createOrUpdateUser, values, getAll) const res = await update(createOrUpdateUser, values, getAll)
if (res === true) { if (res === true) {
setAction('') setAction('')
setIsPermanentConfirmOpen(false)
form.reset() form.reset()
} }
} catch (error) { } catch (error) {
@ -172,6 +192,7 @@ const UsersManagement = () => {
opened={action === 'add' || action === 'edit'} opened={action === 'add' || action === 'edit'}
onClose={() => { onClose={() => {
setAction('') setAction('')
setIsPermanentConfirmOpen(false)
form.reset() form.reset()
}} }}
title={ title={
@ -183,9 +204,15 @@ const UsersManagement = () => {
<form <form
onSubmit={form.onSubmit(async (values) => { onSubmit={form.onSubmit(async (values) => {
setDisableBtn(true) setDisableBtn(true)
action === 'edit' if (action === 'edit') {
? await handleUpdate(values) if (values.is_permanent && !item.is_permanent) {
: await handleCreate(values) setIsPermanentConfirmOpen(true)
} else {
await handleUpdate(values)
}
} else {
await handleCreate(values)
}
setDisableBtn(false) setDisableBtn(false)
})} })}
> >
@ -196,6 +223,7 @@ const UsersManagement = () => {
value={form.values.name} value={form.values.name}
error={form.errors.name} error={form.errors.name}
onChange={(e) => form.setFieldValue('name', e.target.value)} onChange={(e) => form.setFieldValue('name', e.target.value)}
required
/> />
<TextInput <TextInput
@ -204,6 +232,7 @@ const UsersManagement = () => {
value={form.values.email} value={form.values.email}
error={form.errors.email} error={form.errors.email}
onChange={(e) => form.setFieldValue('email', e.target.value)} onChange={(e) => form.setFieldValue('email', e.target.value)}
required
/> />
<MultiSelect <MultiSelect
@ -224,7 +253,25 @@ const UsersManagement = () => {
e!.filter((p) => p.trim() !== '').join(','), e!.filter((p) => p.trim() !== '').join(','),
) )
} }
mb={'md'}
/> />
{action === 'edit' && !item.is_permanent ? (
<Switch
label="Permanent employee"
style={{ width: 'fit-content' }}
checked={form.values.is_permanent}
onChange={(event) =>
form.setFieldValue(
'is_permanent',
event.currentTarget.checked,
)
}
/>
) : (
''
)}
<Box ta={'center'}> <Box ta={'center'}>
{action === 'add' ? ( {action === 'add' ? (
<Button <Button
@ -273,6 +320,50 @@ const UsersManagement = () => {
{info} {info}
</Code> </Code>
</Modal> </Modal>
{/* Confirm change to permanent employee */}
<Modal
opened={isPermanentConfirmOpen}
onClose={() => setIsPermanentConfirmOpen(false)}
centered
size="sm"
classNames={{
content: classes.deleteModal,
}}
>
<Text className={classes.deleteModalTitle}>Confirm Update</Text>
<Text className={classes.deleteModalContent}>
This action will change the employment type from{' '}
<strong>Probation</strong> to <strong>Permanent</strong>.
</Text>
<Text className={classes.deleteModalContent}>
Are you sure you want to proceed?
</Text>
<Box className={classes.deleteModalFooter}>
<Button
variant="outline"
onClick={() => {
setIsPermanentConfirmOpen(false)
}}
disabled={disableBtn}
>
Cancel
</Button>
<Button
className={classes.deleteButton}
onClick={async () => {
setDisableBtn(true)
await handleUpdate(form.values)
setDisableBtn(false)
}}
disabled={disableBtn}
>
Confirm
</Button>
</Box>
</Modal>
<Dialog <Dialog
className={classes.dialog} className={classes.dialog}
opened={action === 'delete'} opened={action === 'delete'}

View File

@ -76,6 +76,7 @@ export type TUser = {
email: string email: string
name: string name: string
permission: string permission: string
is_permanent: boolean
} }
export type DataReason = { export type DataReason = {