1048 lines
31 KiB
Svelte
1048 lines
31 KiB
Svelte
<script>
|
|
import "$lib/global.css";
|
|
import { path } from "@tauri-apps/api";
|
|
import Database from "@tauri-apps/plugin-sql";
|
|
// import { writeTextFile, BaseDirectory } from "@tauri-apps/plugin-fs";
|
|
|
|
import ScreenWrap from "$lib/components/ui/ScreenWrap.svelte";
|
|
import Dialog from "$lib/components/ui/Dialog.svelte";
|
|
|
|
import Field from "$lib/components/form/Field.svelte";
|
|
import TextInput from "$lib/components/form/TextInput.svelte";
|
|
import NumberInput from "$lib/components/form/NumberInput.svelte";
|
|
import ItemList from "$lib/components/form/ItemList.svelte";
|
|
// import DateInput from "$lib/components/form/DateInput.svelte";
|
|
import PhoneInput from "$lib/components/form/PhoneInput.svelte";
|
|
import Select from "$lib/components/form/Select.svelte";
|
|
|
|
import Table from "$lib/components/table/Table.svelte";
|
|
import Tr from "$lib/components/table/Tr.svelte";
|
|
import Td from "$lib/components/table/Td.svelte";
|
|
import Atd from "$lib/components/table/Atd.svelte";
|
|
|
|
import TableCudButtons from "$lib/components/shorts/TableCUDButtons.svelte";
|
|
import TableButtonsWrap from "$lib/components/shorts/TableButtonsWrap.svelte";
|
|
import ViewTable from "$lib/components/shorts/ViewTable.svelte";
|
|
import TableListShort from "$lib/components/shorts/TableListShort.svelte";
|
|
|
|
/** @type {Database} */
|
|
let db;
|
|
|
|
async function load_db() {
|
|
// dev
|
|
db = await Database.load(`sqlite:${await path.resolve()}/../db/data.db`);
|
|
|
|
// db = await Database.load(`sqlite:${await path.resolve()}/db/data.db`);
|
|
|
|
await db.execute(`
|
|
CREATE TABLE IF NOT EXISTS EmployeeStatus (id INTEGER PRIMARY KEY, name VARCHAR(256));
|
|
|
|
CREATE TABLE IF NOT EXISTS Employees (
|
|
id INTEGER PRIMARY KEY,
|
|
employee_status_id INTEGER REFERENCES EmployeeStatus(id) ON DELETE CASCADE,
|
|
fname VARCHAR(100),
|
|
sname VARCHAR(100),
|
|
tname VARCHAR(100)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS AccountAccessLevel (id INTEGER PRIMARY KEY, name VARCHAR(256));
|
|
|
|
CREATE TABLE IF NOT EXISTS Accounts (
|
|
id INTEGER PRIMARY KEY,
|
|
employee_id INTEGER REFERENCES Employees(id),
|
|
account_access_level_id INTEGER REFERENCES AccountAccessLevel(id),
|
|
login VARCHAR(256),
|
|
password VARCHAR(256)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS Clients (
|
|
id INTEGER PRIMARY KEY,
|
|
phone VARCHAR(36),
|
|
fname VARCHAR(100),
|
|
sname VARCHAR(100),
|
|
tname VARCHAR(100)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS RequestStatus (id INTEGER PRIMARY KEY, name VARCHAR(256));
|
|
|
|
CREATE TABLE IF NOT EXISTS RequestType (id INTEGER PRIMARY KEY, name VARCHAR(256));
|
|
|
|
CREATE TABLE IF NOT EXISTS Requests (
|
|
id INTEGER PRIMARY KEY,
|
|
client_id INTEGER REFERENCES Clients(id) ON DELETE CASCADE,
|
|
employee_id INTEGER REFERENCES Employees(id) ON DELETE CASCADE,
|
|
request_status_id INTEGER REFERENCES RequestStatus(id) ON DELETE CASCADE DEFAULT 1,
|
|
request_type_id INTEGER REFERENCES RequestType(id) ON DELETE CASCADE,
|
|
initial_date DATE DEFAULT CURRENT_TIMESTAMP, -- not editable by user
|
|
description TEXT,
|
|
duration FLOAT NULL -- hours
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS Ingredients (id INTEGER PRIMARY KEY, name VARCHAR(256), price INTEGER);
|
|
|
|
CREATE TABLE IF NOT EXISTS Pizzas (
|
|
id INTEGER PRIMARY KEY,
|
|
name VARCHAR(256),
|
|
price INTEGER
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS PizzasIngredientsJoin (
|
|
id INTEGER PRIMARY KEY,
|
|
pizza_id INTEGER REFERENCES Pizzas(id) ON DELETE CASCADE,
|
|
ingredient_id INTEGER REFERENCES Ingredients(id) ON DELETE CASCADE
|
|
);
|
|
|
|
|
|
DROP TABLE IF EXISTS IdBuffer;
|
|
CREATE TABLE IF NOT EXISTS IdBuffer (id INTEGER);
|
|
`);
|
|
}
|
|
|
|
/** @typedef Page
|
|
* @property {Object} tables
|
|
* @property {Object} viewes
|
|
*/
|
|
|
|
const db_scheme = {
|
|
/** @type Page */
|
|
Запросы: {
|
|
/** @type {any} */
|
|
tables: {
|
|
Ingredients: "Ингридиенты",
|
|
Pizzas: "Пиццы",
|
|
PizzasIngredientsJoin: "test",
|
|
Requests: "Запросы",
|
|
Clients: "Клиенты",
|
|
},
|
|
/** @type {any} */
|
|
viewes: {
|
|
RequestCount: "Количество заявок",
|
|
AvgRequestTime: "Среднее время заявок",
|
|
StatByType: "Статистика по типам",
|
|
},
|
|
},
|
|
/** @type Page */
|
|
Сотрудники: {
|
|
/** @type {any} */
|
|
tables: {
|
|
Employees: "Сотрудники",
|
|
Accounts: "Аккаунты",
|
|
AccountAccessLevel: "Доступ",
|
|
},
|
|
/** @type {any} */
|
|
viewes: {},
|
|
},
|
|
|
|
/** @type Page */
|
|
Списки: {
|
|
/** @type {any} */
|
|
tables: {
|
|
RequestStatus: "Статус запроса",
|
|
RequestType: "Тип запроса",
|
|
EmployeeStatus: "Должность",
|
|
},
|
|
/** @type {any} */
|
|
viewes: {},
|
|
},
|
|
};
|
|
|
|
const data_access = {
|
|
admin: true,
|
|
dicrector: {
|
|
Запросы: [
|
|
"Requests",
|
|
"Clients",
|
|
"RequestCount",
|
|
"AvgRequestTime",
|
|
"StatByType",
|
|
],
|
|
Сотрудники: ["Employees", "Accounts"],
|
|
Списки: ["RequestStatus", "RequestType", "EmployeeStatus"],
|
|
},
|
|
|
|
worker: {
|
|
Запросы: ["Requests", "Clients"],
|
|
},
|
|
};
|
|
|
|
/** @type {any} */
|
|
export let current_item = {};
|
|
|
|
let is_item_dialog_open = false;
|
|
let is_dialog_item_add = false;
|
|
let is_login_requied = false;
|
|
|
|
/**
|
|
* @param {string} access_level
|
|
* @param {string} tab_name
|
|
* @param {string | null} name
|
|
*/
|
|
function check_access(access_level, tab_name, name) {
|
|
// @ts-ignore
|
|
if (data_access[access_level] === true) return true;
|
|
|
|
// @ts-ignore
|
|
if (Object.hasOwn(data_access[access_level], tab_name) && name === null)
|
|
return true;
|
|
|
|
// @ts-ignore
|
|
return data_access[access_level][tab_name].includes(name);
|
|
}
|
|
|
|
/**
|
|
@param {string} login
|
|
@param {string} passowrd
|
|
*/
|
|
async function check_login(login, passowrd) {
|
|
const access_type =
|
|
await db.select(`SELECT AccountAccessLevel.name FROM Accounts
|
|
JOIN AccountAccessLevel ON AccountAccessLevel.id = Accounts.account_access_level_id
|
|
WHERE Accounts.login = "${login}" AND Accounts.password = "${passowrd}";`);
|
|
if (access_type.length === 0) {
|
|
return [false, ""];
|
|
} else {
|
|
return [true, access_type[0].name];
|
|
}
|
|
}
|
|
|
|
/**
|
|
@param {Array<number>} ar
|
|
*/
|
|
async function id_buffer(ar) {
|
|
await db.execute(`delete from IdBuffer;
|
|
insert into IdBuffer (id) values (${ar.join("), (")});`);
|
|
}
|
|
</script>
|
|
|
|
<ScreenWrap
|
|
{db}
|
|
{db_scheme}
|
|
{load_db}
|
|
{check_access}
|
|
{check_login}
|
|
{is_login_requied}
|
|
bind:is_item_dialog_open
|
|
bind:is_dialog_item_add
|
|
bind:current_item
|
|
let:current_page
|
|
let:current_table
|
|
let:current_view
|
|
let:is_view_open
|
|
let:cur_dialog_name
|
|
let:toggle_add_dialog
|
|
let:open_item_edit
|
|
let:sql_update_short
|
|
let:sql_insert_short
|
|
let:sql_delete_short
|
|
>
|
|
{#if !is_view_open && current_page === "Запросы"}
|
|
<!-- CREATE TABLE IF NOT EXISTS PizzasIngredientsJoin ( -->
|
|
<!-- id INTEGER PRIMARY KEY, -->
|
|
<!-- pizza_id INTEGER REFERENCES Pizzas(id) ON DELETE CASCADE -->
|
|
<!-- ingredient_id INTEGER REFERENCES Ingredients(id) ON DELETE CASCADE -->
|
|
<!-- ); -->
|
|
<!-- CREATE TABLE IF NOT EXISTS Pizzas ( -->
|
|
<!-- id INTEGER PRIMARY KEY, -->
|
|
<!-- name VARCHAR(256), -->
|
|
<!-- price INTEGER -->
|
|
<!-- ); -->
|
|
{#if current_table === "Pizzas"}
|
|
{@const cur_cols = ["name", "price"]}
|
|
<Dialog
|
|
bind:is_open={is_item_dialog_open}
|
|
name={cur_dialog_name}
|
|
let:form
|
|
>
|
|
{#if !is_dialog_item_add}
|
|
<h1>id {current_item.id}</h1>
|
|
{/if}
|
|
<Field name={"название"}>
|
|
<TextInput bind:value={current_item.name}></TextInput>
|
|
</Field>
|
|
|
|
<Field name={"Ингридиенты"} is_vertical={true}>
|
|
<ItemList
|
|
bind:value={current_item.ingredients_ids}
|
|
item_list_query={db.select("select id, name from Ingredients")}
|
|
on_change={async () => {
|
|
await id_buffer(current_item.ingredients_ids);
|
|
const query = `
|
|
select sum(price) as value
|
|
from Ingredients
|
|
join IdBuffer on IdBuffer.id = Ingredients.id
|
|
`;
|
|
const price = await db.select(query);
|
|
current_item.price = price[0].value;
|
|
}}
|
|
></ItemList>
|
|
</Field>
|
|
|
|
<Field name={"цена"}>
|
|
<NumberInput bind:value={current_item.price}></NumberInput>
|
|
</Field>
|
|
|
|
<TableCudButtons
|
|
{form}
|
|
bind:is_dialog_item_add
|
|
on_add={async () => {
|
|
const las_id = await sql_insert_short(
|
|
current_table,
|
|
cur_cols,
|
|
"returning id",
|
|
);
|
|
console.log(las_id.lastInsertId);
|
|
|
|
const query = `insert into PizzasIngredientsJoin (pizza_id, ingredient_id) values
|
|
${current_item.ingredients_ids.map((el) => "(" + las_id.lastInsertId + "," + el + ")").join(",")}
|
|
`;
|
|
console.log(query);
|
|
await db.execute(query);
|
|
}}
|
|
on_save={async () => {
|
|
const query = `
|
|
delete from PizzasIngredientsJoin where pizza_id = ${current_item.id};
|
|
insert into PizzasIngredientsJoin (pizza_id, ingredient_id) values
|
|
${current_item.ingredients_ids.map((el) => "(" + current_item.id + "," + el + ")").join(",")}
|
|
`;
|
|
await db.execute(query);
|
|
await sql_update_short(current_table, cur_cols);
|
|
}}
|
|
on_delete={sql_delete_short}
|
|
></TableCudButtons>
|
|
</Dialog>
|
|
<TableButtonsWrap
|
|
{current_table}
|
|
{current_item}
|
|
{toggle_add_dialog}
|
|
on_add_click={() => {
|
|
current_item = {
|
|
id: 0,
|
|
name: "",
|
|
price: 0,
|
|
ingredients_ids: [],
|
|
};
|
|
}}
|
|
columns={cur_cols}
|
|
let:is_searching
|
|
let:search_query_result
|
|
>
|
|
<Table
|
|
{is_searching}
|
|
search_query={db.select(search_query_result)}
|
|
columns={["id", ...cur_cols]}
|
|
query={db.select(`select * from ${current_table}`)}
|
|
let:item
|
|
let:index
|
|
>
|
|
<Tr
|
|
{index}
|
|
on_click={async () => {
|
|
const ingredients_ids = await db.select(
|
|
`select ingredient_id from PizzasIngredientsJoin where pizza_id = ${item.id}`,
|
|
);
|
|
open_item_edit(item);
|
|
current_item.ingredients_ids = ingredients_ids.map(
|
|
(/** @type {any} */ el) => el.ingredient_id,
|
|
);
|
|
}}
|
|
>
|
|
<Atd {item} names={["id", ...cur_cols]}></Atd>
|
|
</Tr>
|
|
</Table>
|
|
</TableButtonsWrap>
|
|
{:else if current_table === "PizzasIngredientsJoin"}
|
|
{@const cur_cols = ["pizza_id", "ingredient_id"]}
|
|
<Dialog
|
|
bind:is_open={is_item_dialog_open}
|
|
name={cur_dialog_name}
|
|
let:form
|
|
>
|
|
{#if !is_dialog_item_add}
|
|
<h1>id {current_item.id}</h1>
|
|
{/if}
|
|
<Field name={"питса"}>
|
|
<Select
|
|
bind:value={current_item.pizza_id}
|
|
query={db.select("select id, name from Pizzas")}
|
|
let:vtype
|
|
>
|
|
{vtype.name}
|
|
{vtype.id}
|
|
</Select>
|
|
</Field>
|
|
<Field name={"ингридиент"}>
|
|
<Select
|
|
bind:value={current_item.ingredient_id}
|
|
query={db.select("select id, name from Ingredients")}
|
|
let:vtype
|
|
>
|
|
{vtype.name}
|
|
{vtype.id}
|
|
</Select>
|
|
</Field>
|
|
<TableCudButtons
|
|
{form}
|
|
bind:is_dialog_item_add
|
|
on_add={async () => {
|
|
await sql_insert_short(current_table, cur_cols);
|
|
}}
|
|
on_save={async () => {
|
|
await sql_update_short(current_table, cur_cols);
|
|
}}
|
|
on_delete={sql_delete_short}
|
|
></TableCudButtons>
|
|
</Dialog>
|
|
<TableButtonsWrap
|
|
{current_table}
|
|
{current_item}
|
|
{toggle_add_dialog}
|
|
on_add_click={() => {
|
|
current_item = {
|
|
id: 0,
|
|
pizza_id: null,
|
|
ingredient_id: null,
|
|
};
|
|
}}
|
|
columns={cur_cols}
|
|
let:is_searching
|
|
let:search_query_result
|
|
>
|
|
<Table
|
|
{is_searching}
|
|
search_query={db.select(search_query_result)}
|
|
columns={["id", "питса", "ингридиент"]}
|
|
query={db.select(`select * from ${current_table}`)}
|
|
let:item
|
|
let:index
|
|
>
|
|
<Tr {index} on_click={() => open_item_edit(item)}>
|
|
<Atd {item} names={["id", ...cur_cols]}></Atd>
|
|
</Tr>
|
|
</Table>
|
|
</TableButtonsWrap>
|
|
{:else if current_table === "Ingredients"}
|
|
{@const cur_cols = ["name", "price"]}
|
|
<Dialog
|
|
bind:is_open={is_item_dialog_open}
|
|
name={cur_dialog_name}
|
|
let:form
|
|
>
|
|
{#if !is_dialog_item_add}
|
|
<h1>id {current_item.id}</h1>
|
|
{/if}
|
|
<Field name={"название"}>
|
|
<TextInput bind:value={current_item.name}></TextInput>
|
|
</Field>
|
|
<Field name={"цена"}>
|
|
<NumberInput bind:value={current_item.price}></NumberInput>
|
|
</Field>
|
|
<TableCudButtons
|
|
{form}
|
|
bind:is_dialog_item_add
|
|
on_add={async () => {
|
|
await sql_insert_short(current_table, cur_cols);
|
|
}}
|
|
on_save={async () => {
|
|
await sql_update_short(current_table, cur_cols);
|
|
}}
|
|
on_delete={sql_delete_short}
|
|
></TableCudButtons>
|
|
</Dialog>
|
|
<TableButtonsWrap
|
|
{current_table}
|
|
{current_item}
|
|
{toggle_add_dialog}
|
|
on_add_click={() => {
|
|
current_item = {
|
|
id: 0,
|
|
name: "",
|
|
price: 0,
|
|
};
|
|
}}
|
|
columns={cur_cols}
|
|
let:is_searching
|
|
let:search_query_result
|
|
>
|
|
<Table
|
|
{is_searching}
|
|
search_query={db.select(search_query_result)}
|
|
columns={["id", ...cur_cols]}
|
|
query={db.select(`select * from ${current_table}`)}
|
|
let:item
|
|
let:index
|
|
>
|
|
<Tr {index} on_click={() => open_item_edit(item)}>
|
|
<Atd {item} names={["id", ...cur_cols]}></Atd>
|
|
</Tr>
|
|
</Table>
|
|
</TableButtonsWrap>
|
|
{:else if current_table === "Clients"}
|
|
<Dialog
|
|
bind:is_open={is_item_dialog_open}
|
|
name={cur_dialog_name}
|
|
let:form
|
|
>
|
|
{#if !is_dialog_item_add}
|
|
<h1>id {current_item.id}</h1>
|
|
{/if}
|
|
<Field name={"сотовый"}>
|
|
<PhoneInput bind:phone={current_item.phone}></PhoneInput>
|
|
</Field>
|
|
<Field name={"Имя"}>
|
|
<TextInput bind:value={current_item.fname}></TextInput>
|
|
</Field>
|
|
<Field name={"Фамилия"}>
|
|
<TextInput bind:value={current_item.sname}></TextInput>
|
|
</Field>
|
|
<Field name={"Отчество"}>
|
|
<TextInput bind:value={current_item.tname}></TextInput>
|
|
</Field>
|
|
{@const cur_cols = ["phone", "fname", "sname", "tname"]}
|
|
<TableCudButtons
|
|
{form}
|
|
bind:is_dialog_item_add
|
|
on_add={async () => {
|
|
await sql_insert_short(current_table, cur_cols);
|
|
}}
|
|
on_save={async () => {
|
|
await sql_update_short(current_table, cur_cols);
|
|
}}
|
|
on_delete={sql_delete_short}
|
|
></TableCudButtons>
|
|
</Dialog>
|
|
<TableButtonsWrap
|
|
{current_table}
|
|
{current_item}
|
|
{toggle_add_dialog}
|
|
on_add_click={() => {
|
|
current_item = {
|
|
id: 0,
|
|
phone: "+7 (",
|
|
fname: "",
|
|
sname: "",
|
|
tname: "",
|
|
};
|
|
}}
|
|
columns={["phone", "fname", "sname", "tname"]}
|
|
let:is_searching
|
|
let:search_query_result
|
|
>
|
|
<Table
|
|
{is_searching}
|
|
search_query={db.select(search_query_result)}
|
|
columns={["id", "сотовый", "фио"]}
|
|
query={db.select(`select * from ${current_table}`)}
|
|
let:item
|
|
let:index
|
|
>
|
|
<Tr {index} on_click={() => open_item_edit(item)}>
|
|
<Atd {item} names={["id", "phone"]}></Atd>
|
|
<Td>{item.sname} {item.fname[0]}.{item.tname[0]}</Td>
|
|
</Tr>
|
|
</Table>
|
|
</TableButtonsWrap>
|
|
{:else if current_table === "Requests"}
|
|
<Dialog
|
|
bind:is_open={is_item_dialog_open}
|
|
name={cur_dialog_name}
|
|
let:form
|
|
>
|
|
{#if !is_dialog_item_add}
|
|
<h1>id {current_item.id}</h1>
|
|
{/if}
|
|
<Field name={"Клиент"}>
|
|
<Select
|
|
bind:value={current_item.client_id}
|
|
query={db.select("select id, fname, sname, tname from Clients")}
|
|
let:vtype
|
|
>
|
|
{vtype.id}
|
|
{vtype.sname}
|
|
{vtype.sname[0]}. {vtype.tname[0]}.
|
|
</Select>
|
|
</Field>
|
|
<Field name={"Ответсвтенный"}>
|
|
<Select
|
|
bind:value={current_item.employee_id}
|
|
query={db.select("select id, fname, sname, tname from Employees")}
|
|
let:vtype
|
|
>
|
|
{vtype.id}
|
|
{vtype.sname}
|
|
{vtype.sname[0]}. {vtype.tname[0]}.
|
|
</Select>
|
|
</Field>
|
|
{#if !is_dialog_item_add}
|
|
<Field name={"Статус"}>
|
|
<Select
|
|
bind:value={current_item.request_status_id}
|
|
query={db.select("select id, name from RequestStatus")}
|
|
let:vtype
|
|
>
|
|
{vtype.id}
|
|
{vtype.name}
|
|
</Select>
|
|
</Field>
|
|
{/if}
|
|
<Field name={"Тип запроса"}>
|
|
<Select
|
|
bind:value={current_item.request_type_id}
|
|
query={db.select("select id, name from RequestType")}
|
|
let:vtype
|
|
>
|
|
{vtype.id}
|
|
{vtype.name}
|
|
</Select>
|
|
</Field>
|
|
{#if !is_dialog_item_add}
|
|
<h1>Дата начала {current_item.initial_date}</h1>
|
|
{/if}
|
|
<Field name={"Описание запроса"}>
|
|
<TextInput is_input={false} bind:value={current_item.description}
|
|
></TextInput>
|
|
</Field>
|
|
{#if !is_dialog_item_add}
|
|
<Field name={"Время"}>
|
|
<NumberInput
|
|
is_required={false}
|
|
is_float={true}
|
|
bind:value={current_item.duration}
|
|
></NumberInput>
|
|
</Field>
|
|
{/if}
|
|
{@const cur_cols = [
|
|
"client_id",
|
|
"employee_id",
|
|
"request_status_id",
|
|
"request_type_id",
|
|
"initial_date",
|
|
"description",
|
|
"duration",
|
|
]}
|
|
|
|
<TableCudButtons
|
|
{form}
|
|
bind:is_dialog_item_add
|
|
on_add={async () => {
|
|
await sql_insert_short(current_table, [
|
|
"client_id",
|
|
"employee_id",
|
|
"request_status_id",
|
|
"request_type_id",
|
|
"description",
|
|
"duration",
|
|
]);
|
|
}}
|
|
on_save={async () => {
|
|
await sql_update_short(current_table, cur_cols);
|
|
}}
|
|
on_delete={sql_delete_short}
|
|
></TableCudButtons>
|
|
</Dialog>
|
|
<TableButtonsWrap
|
|
{current_table}
|
|
{current_item}
|
|
{toggle_add_dialog}
|
|
on_add_click={() => {
|
|
current_item = {
|
|
id: 0,
|
|
client_id: 0,
|
|
employee_id: 1,
|
|
request_status_id: 1,
|
|
request_type_id: 1,
|
|
description: "",
|
|
duration: null,
|
|
};
|
|
}}
|
|
columns={[
|
|
"client_id",
|
|
"employee_id",
|
|
"request_status_id",
|
|
"request_type_id",
|
|
"initial_date",
|
|
"description",
|
|
"duration",
|
|
]}
|
|
ex_params={[
|
|
{
|
|
name: "Clients.fname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "Clients.sname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "Clients.tname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "Employees.fname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "Employees.sname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "Employees.tname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "RequestStatus.name",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "RequestType.name",
|
|
is_number: false,
|
|
},
|
|
]}
|
|
joins={`
|
|
JOIN Clients on Clients.id = Requests.client_id
|
|
JOIN Employees on Employees.id = Requests.employee_id
|
|
JOIN RequestStatus on RequestStatus.id = Requests.request_status_id
|
|
JOIN RequestType on RequestType.id = Requests.request_type_id
|
|
`}
|
|
let:is_searching
|
|
let:search_query_result
|
|
>
|
|
<Table
|
|
{is_searching}
|
|
search_query={db.select(search_query_result)}
|
|
columns={[
|
|
"id",
|
|
"клиент",
|
|
"ответсвенный",
|
|
"статус",
|
|
"тип",
|
|
"дата начала",
|
|
// "описание",
|
|
"длительность",
|
|
]}
|
|
query={db.select(`select * from ${current_table}`)}
|
|
let:item
|
|
let:index
|
|
>
|
|
<Tr {index} on_click={() => open_item_edit(item)}>
|
|
<Td>
|
|
{item.id}
|
|
</Td>
|
|
<Td>
|
|
{#await db.select(`select fname, sname, tname from Clients where id = ${item.client_id}`) then data}
|
|
{data[0].fname} {data[0].sname[0]}. {data[0].tname[0]}.
|
|
{/await}
|
|
</Td>
|
|
<Td>
|
|
{#await db.select(`select id, fname, sname, tname from Employees where id = ${item.employee_id}`) then data}
|
|
{data[0].fname} {data[0].sname[0]}. {data[0].tname[0]}.
|
|
{/await}
|
|
</Td>
|
|
<Td>
|
|
{#await db.select(`select id, name from RequestStatus where id = ${item.request_status_id}`) then data}
|
|
{data[0].name}
|
|
{/await}
|
|
</Td>
|
|
<Td>
|
|
{#await db.select(`select id, name from RequestType where id = ${item.request_type_id}`) then data}
|
|
{data[0].name}
|
|
{/await}
|
|
</Td>
|
|
<Atd {item} names={["initial_date", "duration"]}></Atd>
|
|
</Tr>
|
|
</Table>
|
|
</TableButtonsWrap>
|
|
{/if}
|
|
{:else if is_view_open}
|
|
{#if current_view === "RequestCount"}
|
|
<ViewTable
|
|
query={db.select(
|
|
`SELECT 'значение' AS name, COUNT(id) AS value FROM Requests;`,
|
|
)}
|
|
columns={["name", "aa"]}
|
|
names={["name", "value"]}
|
|
></ViewTable>
|
|
{:else if current_view === "AvgRequestTime"}
|
|
<ViewTable
|
|
query={db.select(
|
|
`SELECT 'значение' AS name, AVG(duration) AS value
|
|
FROM Requests
|
|
WHERE duration NOT NULL;`,
|
|
)}
|
|
columns={["name", "value"]}
|
|
names={["name", "value"]}
|
|
></ViewTable>
|
|
{:else if current_view === "StatByType"}
|
|
<ViewTable
|
|
query={db.select(`
|
|
SELECT
|
|
RequestType.name AS type_name,
|
|
AVG(duration) AS avg_duratino,
|
|
COUNT(request_type_id) as type_count
|
|
FROM Requests
|
|
JOIN RequestType on RequestType.id = Requests.request_type_id
|
|
WHERE duration
|
|
GROUP BY request_type_id;
|
|
`)}
|
|
columns={["название", "среднее время", "количество"]}
|
|
names={["type_name", "avg_duratino", "type_count"]}
|
|
></ViewTable>
|
|
{/if}
|
|
{/if}
|
|
|
|
{#if current_page === "Сотрудники"}
|
|
{#if current_table === "Employees"}
|
|
<Dialog
|
|
bind:is_open={is_item_dialog_open}
|
|
name={cur_dialog_name}
|
|
let:form
|
|
>
|
|
{#if !is_dialog_item_add}
|
|
<h1>id {current_item.id}</h1>
|
|
{/if}
|
|
|
|
<Field name={"Должность"}>
|
|
<Select
|
|
bind:value={current_item.employee_status_id}
|
|
query={db.select("select id, name from EmployeeStatus")}
|
|
let:vtype
|
|
>
|
|
{vtype.id}
|
|
{vtype.name}
|
|
</Select>
|
|
</Field>
|
|
|
|
<Field name={"Имя"}>
|
|
<TextInput bind:value={current_item.fname}></TextInput>
|
|
</Field>
|
|
|
|
<Field name={"Фамилия"}>
|
|
<TextInput bind:value={current_item.sname}></TextInput>
|
|
</Field>
|
|
|
|
<Field name={"Отчество"}>
|
|
<TextInput bind:value={current_item.tname}></TextInput>
|
|
</Field>
|
|
|
|
{@const cur_cols = ["employee_status_id", "fname", "sname", "tname"]}
|
|
|
|
<TableCudButtons
|
|
{form}
|
|
bind:is_dialog_item_add
|
|
on_add={async () => {
|
|
await sql_insert_short(current_table, cur_cols);
|
|
}}
|
|
on_save={async () => {
|
|
await sql_update_short(current_table, cur_cols);
|
|
}}
|
|
on_delete={sql_delete_short}
|
|
></TableCudButtons>
|
|
</Dialog>
|
|
|
|
<TableButtonsWrap
|
|
{current_table}
|
|
{current_item}
|
|
{toggle_add_dialog}
|
|
on_add_click={() => {
|
|
current_item = {
|
|
id: 0,
|
|
employee_status_id: 1,
|
|
fname: "",
|
|
sname: "",
|
|
tname: "",
|
|
};
|
|
}}
|
|
columns={["employee_status_id", "fname", "sname", "tname"]}
|
|
joins={`JOIN EmployeeStatus on EmployeeStatus.id = Employees.employee_status_id`}
|
|
ex_params={[
|
|
{
|
|
name: "EmployeeStatus.name",
|
|
is_number: false,
|
|
},
|
|
]}
|
|
let:is_searching
|
|
let:search_query_result
|
|
>
|
|
<Table
|
|
{is_searching}
|
|
search_query={db.select(search_query_result)}
|
|
columns={["id", "должность", "фио"]}
|
|
query={db.select(`select * from ${current_table}`)}
|
|
let:item
|
|
let:index
|
|
>
|
|
<Tr {index} on_click={() => open_item_edit(item)}>
|
|
<Atd {item} names={["id"]}></Atd>
|
|
<Td>
|
|
{#await db.select(`select name from EmployeeStatus where id = ${item.employee_status_id}`) then data}
|
|
{data[0].name}
|
|
{/await}
|
|
</Td>
|
|
|
|
<Td>{item.sname} {item.fname[0]}.{item.tname[0]}</Td>
|
|
</Tr>
|
|
</Table>
|
|
</TableButtonsWrap>
|
|
{:else if current_table === "Accounts"}
|
|
<Dialog
|
|
bind:is_open={is_item_dialog_open}
|
|
name={cur_dialog_name}
|
|
let:form
|
|
>
|
|
{#if !is_dialog_item_add}
|
|
<h1>id {current_item.id}</h1>
|
|
{/if}
|
|
|
|
<Field name={"Сотрудник"}>
|
|
<Select
|
|
bind:value={current_item.employee_id}
|
|
query={db.select("select id, fname, sname, tname from Employees")}
|
|
let:vtype
|
|
>
|
|
{vtype.id}
|
|
{vtype.fname}
|
|
{vtype.sname[0]}. {vtype.tname[0]}.
|
|
</Select>
|
|
</Field>
|
|
|
|
<Field name={"Доступ"}>
|
|
<Select
|
|
bind:value={current_item.account_access_level_id}
|
|
query={db.select("select id, name from AccountAccessLevel")}
|
|
let:vtype
|
|
>
|
|
{vtype.id}
|
|
{vtype.name}
|
|
</Select>
|
|
</Field>
|
|
|
|
<Field name={"login"}>
|
|
<TextInput bind:value={current_item.login}></TextInput>
|
|
</Field>
|
|
|
|
<Field name={"Пароль"}>
|
|
<TextInput bind:value={current_item.password}></TextInput>
|
|
</Field>
|
|
|
|
{@const cur_cols = [
|
|
"employee_id",
|
|
"account_access_level_id",
|
|
"login",
|
|
"password",
|
|
]}
|
|
|
|
<TableCudButtons
|
|
{form}
|
|
bind:is_dialog_item_add
|
|
on_add={async () => {
|
|
await sql_insert_short(current_table, cur_cols);
|
|
}}
|
|
on_save={async () => {
|
|
await sql_update_short(current_table, cur_cols);
|
|
}}
|
|
on_delete={sql_delete_short}
|
|
></TableCudButtons>
|
|
</Dialog>
|
|
|
|
<TableButtonsWrap
|
|
{current_table}
|
|
{current_item}
|
|
{toggle_add_dialog}
|
|
on_add_click={() => {
|
|
current_item = {
|
|
id: 0,
|
|
employee_id: 0,
|
|
account_access_level_id: 0,
|
|
login: "",
|
|
password: "",
|
|
};
|
|
}}
|
|
columns={[
|
|
"employee_id",
|
|
"account_access_level_id",
|
|
"login",
|
|
"password",
|
|
]}
|
|
joins={"JOIN Employees on Accounts.employee_id = Employees.id"}
|
|
ex_params={[
|
|
{
|
|
name: "Employees.fname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "Employees.sname",
|
|
is_number: false,
|
|
},
|
|
{
|
|
name: "Employees.tname",
|
|
is_number: false,
|
|
},
|
|
]}
|
|
let:is_searching
|
|
let:search_query_result
|
|
>
|
|
<Table
|
|
{is_searching}
|
|
search_query={db.select(search_query_result)}
|
|
columns={["id", "Сотрудник", "Доступ", "Логин"]}
|
|
query={db.select(`select * from ${current_table}`)}
|
|
let:item
|
|
let:index
|
|
>
|
|
<Tr {index} on_click={() => open_item_edit(item)}>
|
|
<Atd {item} names={["id"]}></Atd>
|
|
<Td>
|
|
{#await db.select(`select id, fname, sname, tname from Employees where id = ${item.employee_id}`) then data}
|
|
{data[0].fname} {data[0].sname[0]}. {data[0].tname[0]}.
|
|
{/await}
|
|
</Td>
|
|
<Td>
|
|
{#await db.select(`select name from AccountAccessLevel where id = ${item.account_access_level_id}`) then data}
|
|
{data[0].name}
|
|
{/await}
|
|
</Td>
|
|
<Atd {item} names={["login"]}></Atd>
|
|
</Tr>
|
|
</Table>
|
|
</TableButtonsWrap>
|
|
{:else if current_table === "AccountAccessLevel"}
|
|
<TableListShort
|
|
{db}
|
|
{cur_dialog_name}
|
|
{current_table}
|
|
bind:is_item_dialog_open
|
|
bind:is_dialog_item_add
|
|
bind:current_item
|
|
query={db.select(`select * from ${current_table}`)}
|
|
columns={["id", "name"]}
|
|
columns_display={["id", "название"]}
|
|
{toggle_add_dialog}
|
|
{open_item_edit}
|
|
{sql_insert_short}
|
|
{sql_update_short}
|
|
{sql_delete_short}
|
|
></TableListShort>
|
|
{/if}
|
|
{/if}
|
|
|
|
{#if !is_view_open && current_page === "Списки"}
|
|
{#if ["RequestStatus", "RequestType", "EmployeeStatus"].includes(current_table)}
|
|
<TableListShort
|
|
{db}
|
|
{cur_dialog_name}
|
|
{current_table}
|
|
bind:is_item_dialog_open
|
|
bind:is_dialog_item_add
|
|
bind:current_item
|
|
query={db.select(`select * from ${current_table}`)}
|
|
columns={["id", "name"]}
|
|
columns_display={["id", "название"]}
|
|
{toggle_add_dialog}
|
|
{open_item_edit}
|
|
{sql_insert_short}
|
|
{sql_update_short}
|
|
{sql_delete_short}
|
|
></TableListShort>
|
|
{/if}
|
|
{/if}
|
|
</ScreenWrap>
|