Index: .init.sql
===================================================================
--- 01.init.sql	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,439 +1,0 @@
-BEGIN;
-
-
-CREATE TABLE IF NOT EXISTS users (
-                                     id BIGSERIAL PRIMARY KEY,
-                                     email VARCHAR(255) NOT NULL UNIQUE,
-    password VARCHAR(255) NOT NULL,
-    phone_number VARCHAR(50) UNIQUE,
-    street VARCHAR(255),
-    city VARCHAR(255)
-    );
-
-CREATE TABLE IF NOT EXISTS employees (
-                                         user_id BIGSERIAL PRIMARY KEY,
-                                         net_salary DECIMAL(10,2),
-    gross_salary DECIMAL(10,2),
-    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS customers (
-                                         user_id BIGSERIAL PRIMARY KEY,
-                                         FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS staff_roles (
-                                           id BIGSERIAL PRIMARY KEY,
-                                           name VARCHAR(255) NOT NULL
-    );
-
-CREATE TABLE IF NOT EXISTS front_staff (
-                                           employee_id BIGSERIAL PRIMARY KEY,
-                                           tip_percent DECIMAL(10,2),
-    staff_role_id BIGINT NOT NULL,
-    FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (staff_role_id) REFERENCES staff_roles (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS back_staff (
-                                          employee_id BIGSERIAL PRIMARY KEY,
-                                          staff_role_id BIGINT NOT NULL,
-                                          FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (staff_role_id) REFERENCES staff_roles (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS managers (
-                                        employee_id BIGSERIAL PRIMARY KEY,
-                                        FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS shifts (
-                                      id BIGSERIAL PRIMARY KEY,
-                                      date DATE NOT NULL,
-                                      start_time TIME NOT NULL,
-                                      end_time TIME NOT NULL,
-                                      manager_id BIGINT NOT NULL,
-                                      FOREIGN KEY (manager_id) REFERENCES managers (employee_id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS assignments (
-                                           id BIGSERIAL PRIMARY KEY,
-                                           clock_in_time TIME,
-                                           clock_out_time TIME,
-                                           manager_id BIGINT NOT NULL,
-                                           employee_id BIGINT NOT NULL,
-                                           shift_id BIGINT NOT NULL,
-                                           FOREIGN KEY (manager_id) REFERENCES managers (employee_id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (shift_id) REFERENCES shifts (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS tables (
-                                      table_number BIGSERIAL PRIMARY KEY,
-                                      seat_capacity INT NOT NULL
-);
-
-CREATE TABLE IF NOT EXISTS reservations (
-                                            id BIGSERIAL PRIMARY KEY,
-                                            user_id BIGINT NOT NULL,
-                                            creation_timestamp TIMESTAMP NOT NULL,
-                                            datetime TIMESTAMP NOT NULL,
-                                            number_of_people BIGINT NOT NULL,
-                                            stay_length DECIMAL(10,2) NULL, --hours
-    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS frontstaff_managed_reservations (
-                                                               id BIGSERIAL PRIMARY KEY,
-                                                               reservation_id BIGINT NOT NULL,
-                                                               front_staff_id BIGINT NOT NULL,
-                                                               table_number BIGINT NOT NULL,
-                                                               FOREIGN KEY (reservation_id) REFERENCES reservations (id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (front_staff_id) REFERENCES front_staff (employee_id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (table_number) REFERENCES tables (table_number) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS categories (
-                                          id BIGSERIAL PRIMARY KEY,
-                                          name VARCHAR(255) NOT NULL,
-    is_available BOOLEAN NOT NULL DEFAULT TRUE
-    );
-
-CREATE TABLE IF NOT EXISTS products (
-                                        id BIGSERIAL PRIMARY KEY,
-                                        name VARCHAR(255) NOT NULL,
-    description VARCHAR(1000) NOT NULL,
-    price DECIMAL(10,2) NOT NULL,
-    category_id BIGINT NOT NULL,
-    manage_inventory BOOLEAN NOT NULL DEFAULT FALSE,
-    tax_class VARCHAR(4) NOT NULL,
-    FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS inventories (
-                                           product_id BIGSERIAL PRIMARY KEY,
-                                           quantity INT NOT NULL,
-                                           restock_level  INT NULL,
-                                           FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS orders (
-                                      id BIGSERIAL PRIMARY KEY,
-                                      status VARCHAR(255) NOT NULL DEFAULT 'PENDING',
-    datetime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
-    );
-
-CREATE TABLE IF NOT EXISTS order_items (
-                                           id BIGSERIAL PRIMARY KEY,
-                                           order_id BIGINT NOT NULL,
-                                           product_id BIGINT NOT NULL,
-                                           is_processed BOOLEAN NOT NULL DEFAULT FALSE,
-                                           quantity INT NOT NULL,
-                                           price DECIMAL(10,2) NOT NULL,
-    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS tab_orders (
-                                          order_id BIGSERIAL PRIMARY KEY,
-                                          front_staff_id BIGINT NOT NULL,
-                                          table_number BIGINT NOT NULL,
-                                          FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (table_number) REFERENCES tables (table_number) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (front_staff_id) REFERENCES front_staff (employee_id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS online_orders (
-                                             order_id BIGSERIAL PRIMARY KEY,
-                                             delivery_address VARCHAR(255) NOT NULL,
-    customer_id BIGINT NOT NULL,
-    FOREIGN KEY (customer_id) REFERENCES customers (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
-    FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
-CREATE TABLE IF NOT EXISTS payments (
-                                        id BIGSERIAL PRIMARY KEY,
-                                        order_id BIGINT NOT NULL,
-                                        amount DECIMAL(10,2) NOT NULL,
-    payment_type VARCHAR(32) NOT NULL,
-    tip_amount DECIMAL(10,2) NOT NULL DEFAULT 0,
-    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE
-    );
-
--- ASSERTIONS
-
-ALTER TABLE employees
-    ADD CONSTRAINT employees_net_salary_nonneg   CHECK (net_salary   IS NULL OR net_salary   >= 0),
-  ADD CONSTRAINT employees_gross_salary_nonneg CHECK (gross_salary IS NULL OR gross_salary >= 0);
-
-ALTER TABLE inventories
-    ADD CONSTRAINT inventories_qty_nonneg CHECK (quantity >= 0),
-  ADD CONSTRAINT inventories_restock_nonneg CHECK (restock_level IS NULL OR restock_level >= 0);
-
-ALTER TABLE products
-    ADD CONSTRAINT products_price_nonneg CHECK (price >= 0);
-
-ALTER TABLE order_items
-    ADD CONSTRAINT order_items_qty_pos CHECK (quantity > 0),
-  ADD CONSTRAINT order_items_price_nonneg CHECK (price >= 0);
-
-ALTER TABLE payments
-    ADD CONSTRAINT payments_amount_nonneg CHECK (amount >= 0),
-  ADD CONSTRAINT payments_tip_nonneg    CHECK (tip_amount >= 0);
-
-ALTER TABLE tables
-    ADD CONSTRAINT tables_capacity_pos CHECK (seat_capacity > 0);
-
-ALTER TABLE reservations
-    ADD CONSTRAINT reservations_people_pos CHECK (number_of_people > 0);
-
-ALTER TABLE front_staff
-    ADD CONSTRAINT front_staff_tip_pct CHECK (tip_percent IS NULL OR (tip_percent >= 0 AND tip_percent <= 100));
-
-
-CREATE OR REPLACE FUNCTION enforce_no_double_booking()
-RETURNS trigger AS $$
-DECLARE
-new_span tsrange;
-  conflict_exists boolean;
-BEGIN
-SELECT tsrange(
-               r.datetime,
-               r.datetime + (COALESCE(r.stay_length, 2) * INTERVAL '1 hour'),
-               '[)'
-           )
-INTO new_span
-FROM reservations r
-WHERE r.id = NEW.reservation_id;
-
-IF new_span IS NULL THEN
-    RAISE EXCEPTION 'Reservation % not found or invalid', NEW.reservation_id;
-END IF;
-
-  -- Check for overlap on same table_number (exclude self on UPDATE)
-SELECT EXISTS (
-    SELECT 1
-    FROM frontstaff_managed_reservations fmr
-             JOIN reservations r2 ON r2.id = fmr.reservation_id
-    WHERE fmr.table_number = NEW.table_number
-      AND (NEW.id IS NULL OR fmr.id <> NEW.id)
-      AND tsrange(
-            r2.datetime,
-            r2.datetime + (COALESCE(r2.stay_length, 2) * INTERVAL '1 hour'),
-            '[)'
-        ) && new_span
-) INTO conflict_exists;
-
-IF conflict_exists THEN
-    RAISE EXCEPTION 'Double booking prevented: table % has overlapping reservations', NEW.table_number;
-END IF;
-
-RETURN NEW;
-END;
-$$ LANGUAGE plpgsql;
-
-DROP TRIGGER IF EXISTS trg_no_double_booking_ins ON frontstaff_managed_reservations;
-CREATE CONSTRAINT TRIGGER trg_no_double_booking_ins
-AFTER INSERT ON frontstaff_managed_reservations
-DEFERRABLE INITIALLY DEFERRED
-FOR EACH ROW EXECUTE FUNCTION enforce_no_double_booking();
-
-DROP TRIGGER IF EXISTS trg_no_double_booking_upd ON frontstaff_managed_reservations;
-CREATE CONSTRAINT TRIGGER trg_no_double_booking_upd
-AFTER UPDATE ON frontstaff_managed_reservations
-                 DEFERRABLE INITIALLY DEFERRED
-                 FOR EACH ROW EXECUTE FUNCTION enforce_no_double_booking();
-
-CREATE INDEX IF NOT EXISTS fmr_table_idx ON frontstaff_managed_reservations (table_number);
-CREATE INDEX IF NOT EXISTS reservations_span_expr_gist
-    ON reservations USING gist (
-    tsrange(
-    datetime,
-    datetime + (COALESCE(stay_length, 2) * INTERVAL '1 hour'),
-    '[)'
-    )
-    );
-CREATE INDEX IF NOT EXISTS idx_payments_order      ON payments(order_id);
-CREATE INDEX IF NOT EXISTS idx_payments_created_at ON payments(created_at);
-
-
-CREATE OR REPLACE FUNCTION fmr_capacity_guard() RETURNS trigger AS $$
-DECLARE
-cap int;
-  party bigint;
-BEGIN
-SELECT seat_capacity INTO cap FROM tables WHERE table_number = NEW.table_number;
-SELECT number_of_people INTO party FROM reservations WHERE id = NEW.reservation_id;
-
-IF cap IS NULL OR party IS NULL THEN
-    RAISE EXCEPTION 'Invalid reservation % or table %', NEW.reservation_id, NEW.table_number;
-END IF;
-
-  IF party > cap THEN
-    RAISE EXCEPTION 'Party size % exceeds capacity % for table %',
-      party, cap, NEW.table_number;
-END IF;
-
-RETURN NEW;
-END;
-$$ LANGUAGE plpgsql;
-
-DROP TRIGGER IF EXISTS trg_fmr_capacity_ins ON frontstaff_managed_reservations;
-CREATE TRIGGER trg_fmr_capacity_ins
-    BEFORE INSERT ON frontstaff_managed_reservations
-    FOR EACH ROW EXECUTE FUNCTION fmr_capacity_guard();
-
-DROP TRIGGER IF EXISTS trg_fmr_capacity_upd ON frontstaff_managed_reservations;
-CREATE TRIGGER trg_fmr_capacity_upd
-    BEFORE UPDATE ON frontstaff_managed_reservations
-    FOR EACH ROW EXECUTE FUNCTION fmr_capacity_guard();
-
-
-CREATE OR REPLACE FUNCTION payments_mark_order_paid() RETURNS trigger AS $$
-BEGIN
-UPDATE orders
-SET status = 'PAID'
-WHERE id = NEW.order_id;
-RETURN NEW;
-END;
-$$ LANGUAGE plpgsql;
-
-DROP TRIGGER IF EXISTS trg_payments_mark_order_paid ON payments;
-CREATE TRIGGER trg_payments_mark_order_paid
-    AFTER INSERT ON payments
-    FOR EACH ROW EXECUTE FUNCTION payments_mark_order_paid();
-
-
-CREATE MATERIALIZED VIEW IF NOT EXISTS mv_payments_daily_channel AS
-WITH orders_channel AS (
-  SELECT
-    o.id AS order_id,
-    CASE
-      WHEN EXISTS (SELECT 1 FROM tab_orders t WHERE t.order_id = o.id) THEN 'TAB'
-      WHEN EXISTS (SELECT 1 FROM online_orders oo WHERE oo.order_id = o.id) THEN 'ONLINE'
-      ELSE 'UNKNOWN'
-    END AS channel
-  FROM orders o
-)
-SELECT
-    (date_trunc('day', p.created_at))::date AS day,
-  oc.channel,
-  COUNT(DISTINCT p.order_id)            AS paid_orders_cnt,
-  SUM(p.amount)::numeric(14,2)          AS revenue,
-  SUM(p.tip_amount)::numeric(14,2)      AS tip_total
-FROM payments p
-    JOIN orders_channel oc ON oc.order_id = p.order_id
-GROUP BY (date_trunc('day', p.created_at))::date, oc.channel;
-
-CREATE UNIQUE INDEX IF NOT EXISTS ux_mv_payments_daily_channel
-    ON mv_payments_daily_channel (day, channel);
-
-REFRESH MATERIALIZED VIEW mv_payments_daily_channel;
-
-
--- DML
-INSERT INTO users(id, email, password, phone_number, street, city)
-VALUES
-    (1, 'test@hotmail.com', 'password1', '070003005', 'Mladinska 3', 'Strumica'),
-    (2, 'test2@hotmail.com', 'password2', '070001002', 'Marsal Tito 10', 'Strumica'),
-    (3, 'test3@hotmail.com', 'password1', '070003003', 'Mladinska 5', 'Strumica'),
-    (4, 'test4@hotmail.com', 'password2', '070004004', 'Marsal Tito 11', 'Strumica'),
-    (5, 'test5@hotmail.com', 'password1', '070005005', 'Mladinska 12', 'Strumica');
-
-INSERT INTO employees(user_id, net_salary, gross_salary)
-VALUES
-    (1, 30000, 40000),
-    (3, 50000, 62000),
-    (4, 35000, 46000),
-    (5, 28000, 37000);
-
-INSERT INTO managers(employee_id)
-VALUES
-    (3);
-
-INSERT INTO staff_roles(id, name)
-VALUES
-    (1, 'Server'),
-    (2, 'Chef'),
-    (3, 'Bartender'),
-    (4, 'Hostess');
-
-INSERT INTO front_staff(employee_id, tip_percent, staff_role_id)
-VALUES
-    (1, .4, 1),
-    (5, 0.1, 4);
-
-INSERT INTO back_staff(employee_id, staff_role_id)
-VALUES
-    (4, 2);
-
-INSERT INTO customers(user_id)
-VALUES
-    (2);
-
-INSERT INTO shifts (id, date, start_time, end_time, manager_id)
-VALUES
-    (1, current_date, '09:00:00', '17:00:00', 3);
-
-INSERT INTO assignments(id, clock_in_time, clock_out_time, manager_id, employee_id, shift_id)
-VALUES
-    (1, NULL, NULL, 3, 1, 1);
-
-INSERT INTO tables(table_number, seat_capacity)
-VALUES
-    (1, 4),
-    (2, 8);
-
-INSERT INTO  reservations(id, user_id, creation_timestamp, datetime, stay_length, number_of_people)
-VALUES
-    (1, 2, now(), now(), NULL, 4);
-
-INSERT INTO frontstaff_managed_reservations(id, reservation_id, front_staff_id, table_number)
-VALUES
-    (1, 1, 5, 1);
-
-INSERT INTO categories(id, name)
-VALUES
-    (1, 'Drinks'),
-    (2, 'Appetizers'),
-    (3, 'Entrees');
-
-INSERT INTO products(id, name, description, price, category_id, manage_inventory, tax_class)
-VALUES
-    (1, 'Coca Cola', 'A classic carbonated soft drink.', 100, 1, TRUE, 'A'),
-    (2, 'Pomfrit so sirenje', 'Crispy french fries topped with melted cheese.', 250, 2, FALSE, 'A');
-
-INSERT INTO inventories(product_id, quantity)
-VALUES
-    (1, 100);
-
-INSERT INTO orders(id, status, datetime)
-VALUES
-    (1, 'PENDING', '2025-01-05 10:00:00'),
-    (2, 'ACCEPTED', '2025-01-05 10:00:00'),
-    (3, 'CONFIRMED', '2025-01-05 11:00:00');
-
-INSERT INTO order_items (id, order_id, product_id, is_processed, quantity, price)
-SELECT 1, 1, 1, TRUE, 3, price FROM products WHERE id = 1
-UNION ALL
-SELECT 2, 1, 2, FALSE, 1, price FROM products WHERE id = 2
-UNION ALL
-SELECT 3, 3, 2, FALSE, 2, price FROM products WHERE id = 2
-UNION ALL
-SELECT 4, 3, 1, FALSE, 2, price FROM products WHERE id = 1;
-
-INSERT INTO tab_orders(order_id, front_staff_id, table_number)
-VALUES
-    (1, 1, 1);
-
-INSERT INTO online_orders(order_id, delivery_address, customer_id)
-VALUES
-    (3, 'Leninova 5', 2);
-
-INSERT INTO payments(id, order_id, amount, payment_type, tip_amount)
-VALUES
-    (1, 3, 700, 'cash', 10);
-
-COMMIT;
Index: backend/01.init.sql
===================================================================
--- backend/01.init.sql	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/01.init.sql	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,439 @@
+BEGIN;
+
+
+CREATE TABLE IF NOT EXISTS users (
+                                     id BIGSERIAL PRIMARY KEY,
+                                     email VARCHAR(255) NOT NULL UNIQUE,
+    password VARCHAR(255) NOT NULL,
+    phone_number VARCHAR(50) UNIQUE,
+    street VARCHAR(255),
+    city VARCHAR(255)
+    );
+
+CREATE TABLE IF NOT EXISTS employees (
+                                         user_id BIGSERIAL PRIMARY KEY,
+                                         net_salary DECIMAL(10,2),
+    gross_salary DECIMAL(10,2),
+    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS customers (
+                                         user_id BIGSERIAL PRIMARY KEY,
+                                         FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS staff_roles (
+                                           id BIGSERIAL PRIMARY KEY,
+                                           name VARCHAR(255) NOT NULL
+    );
+
+CREATE TABLE IF NOT EXISTS front_staff (
+                                           employee_id BIGSERIAL PRIMARY KEY,
+                                           tip_percent DECIMAL(10,2),
+    staff_role_id BIGINT NOT NULL,
+    FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (staff_role_id) REFERENCES staff_roles (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS back_staff (
+                                          employee_id BIGSERIAL PRIMARY KEY,
+                                          staff_role_id BIGINT NOT NULL,
+                                          FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (staff_role_id) REFERENCES staff_roles (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS managers (
+                                        employee_id BIGSERIAL PRIMARY KEY,
+                                        FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS shifts (
+                                      id BIGSERIAL PRIMARY KEY,
+                                      date DATE NOT NULL,
+                                      start_time TIME NOT NULL,
+                                      end_time TIME NOT NULL,
+                                      manager_id BIGINT NOT NULL,
+                                      FOREIGN KEY (manager_id) REFERENCES managers (employee_id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS assignments (
+                                           id BIGSERIAL PRIMARY KEY,
+                                           clock_in_time TIME,
+                                           clock_out_time TIME,
+                                           manager_id BIGINT NOT NULL,
+                                           employee_id BIGINT NOT NULL,
+                                           shift_id BIGINT NOT NULL,
+                                           FOREIGN KEY (manager_id) REFERENCES managers (employee_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (employee_id) REFERENCES employees (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (shift_id) REFERENCES shifts (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS tables (
+                                      table_number BIGSERIAL PRIMARY KEY,
+                                      seat_capacity INT NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS reservations (
+                                            id BIGSERIAL PRIMARY KEY,
+                                            user_id BIGINT NOT NULL,
+                                            creation_timestamp TIMESTAMP NOT NULL,
+                                            datetime TIMESTAMP NOT NULL,
+                                            number_of_people BIGINT NOT NULL,
+                                            stay_length DECIMAL(10,2) NULL, --hours
+    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS frontstaff_managed_reservations (
+                                                               id BIGSERIAL PRIMARY KEY,
+                                                               reservation_id BIGINT NOT NULL,
+                                                               front_staff_id BIGINT NOT NULL,
+                                                               table_number BIGINT NOT NULL,
+                                                               FOREIGN KEY (reservation_id) REFERENCES reservations (id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (front_staff_id) REFERENCES front_staff (employee_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (table_number) REFERENCES tables (table_number) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS categories (
+                                          id BIGSERIAL PRIMARY KEY,
+                                          name VARCHAR(255) NOT NULL,
+    is_available BOOLEAN NOT NULL DEFAULT TRUE
+    );
+
+CREATE TABLE IF NOT EXISTS products (
+                                        id BIGSERIAL PRIMARY KEY,
+                                        name VARCHAR(255) NOT NULL,
+    description VARCHAR(1000) NOT NULL,
+    price DECIMAL(10,2) NOT NULL,
+    category_id BIGINT NOT NULL,
+    manage_inventory BOOLEAN NOT NULL DEFAULT FALSE,
+    tax_class VARCHAR(4) NOT NULL,
+    FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS inventories (
+                                           product_id BIGSERIAL PRIMARY KEY,
+                                           quantity INT NOT NULL,
+                                           restock_level  INT NULL,
+                                           FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS orders (
+                                      id BIGSERIAL PRIMARY KEY,
+                                      status VARCHAR(255) NOT NULL DEFAULT 'PENDING',
+    datetime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+    );
+
+CREATE TABLE IF NOT EXISTS order_items (
+                                           id BIGSERIAL PRIMARY KEY,
+                                           order_id BIGINT NOT NULL,
+                                           product_id BIGINT NOT NULL,
+                                           is_processed BOOLEAN NOT NULL DEFAULT FALSE,
+                                           quantity INT NOT NULL,
+                                           price DECIMAL(10,2) NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS tab_orders (
+                                          order_id BIGSERIAL PRIMARY KEY,
+                                          front_staff_id BIGINT NOT NULL,
+                                          table_number BIGINT NOT NULL,
+                                          FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (table_number) REFERENCES tables (table_number) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (front_staff_id) REFERENCES front_staff (employee_id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS online_orders (
+                                             order_id BIGSERIAL PRIMARY KEY,
+                                             delivery_address VARCHAR(255) NOT NULL,
+    customer_id BIGINT NOT NULL,
+    FOREIGN KEY (customer_id) REFERENCES customers (user_id) ON DELETE CASCADE ON UPDATE CASCADE,
+    FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+CREATE TABLE IF NOT EXISTS payments (
+                                        id BIGSERIAL PRIMARY KEY,
+                                        order_id BIGINT NOT NULL,
+                                        amount DECIMAL(10,2) NOT NULL,
+    payment_type VARCHAR(32) NOT NULL,
+    tip_amount DECIMAL(10,2) NOT NULL DEFAULT 0,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE ON UPDATE CASCADE
+    );
+
+-- ASSERTIONS
+
+ALTER TABLE employees
+    ADD CONSTRAINT employees_net_salary_nonneg   CHECK (net_salary   IS NULL OR net_salary   >= 0),
+  ADD CONSTRAINT employees_gross_salary_nonneg CHECK (gross_salary IS NULL OR gross_salary >= 0);
+
+ALTER TABLE inventories
+    ADD CONSTRAINT inventories_qty_nonneg CHECK (quantity >= 0),
+  ADD CONSTRAINT inventories_restock_nonneg CHECK (restock_level IS NULL OR restock_level >= 0);
+
+ALTER TABLE products
+    ADD CONSTRAINT products_price_nonneg CHECK (price >= 0);
+
+ALTER TABLE order_items
+    ADD CONSTRAINT order_items_qty_pos CHECK (quantity > 0),
+  ADD CONSTRAINT order_items_price_nonneg CHECK (price >= 0);
+
+ALTER TABLE payments
+    ADD CONSTRAINT payments_amount_nonneg CHECK (amount >= 0),
+  ADD CONSTRAINT payments_tip_nonneg    CHECK (tip_amount >= 0);
+
+ALTER TABLE tables
+    ADD CONSTRAINT tables_capacity_pos CHECK (seat_capacity > 0);
+
+ALTER TABLE reservations
+    ADD CONSTRAINT reservations_people_pos CHECK (number_of_people > 0);
+
+ALTER TABLE front_staff
+    ADD CONSTRAINT front_staff_tip_pct CHECK (tip_percent IS NULL OR (tip_percent >= 0 AND tip_percent <= 100));
+
+
+CREATE OR REPLACE FUNCTION enforce_no_double_booking()
+RETURNS trigger AS $$
+DECLARE
+new_span tsrange;
+  conflict_exists boolean;
+BEGIN
+SELECT tsrange(
+               r.datetime,
+               r.datetime + (COALESCE(r.stay_length, 2) * INTERVAL '1 hour'),
+               '[)'
+           )
+INTO new_span
+FROM reservations r
+WHERE r.id = NEW.reservation_id;
+
+IF new_span IS NULL THEN
+    RAISE EXCEPTION 'Reservation % not found or invalid', NEW.reservation_id;
+END IF;
+
+  -- Check for overlap on same table_number (exclude self on UPDATE)
+SELECT EXISTS (
+    SELECT 1
+    FROM frontstaff_managed_reservations fmr
+             JOIN reservations r2 ON r2.id = fmr.reservation_id
+    WHERE fmr.table_number = NEW.table_number
+      AND (NEW.id IS NULL OR fmr.id <> NEW.id)
+      AND tsrange(
+            r2.datetime,
+            r2.datetime + (COALESCE(r2.stay_length, 2) * INTERVAL '1 hour'),
+            '[)'
+        ) && new_span
+) INTO conflict_exists;
+
+IF conflict_exists THEN
+    RAISE EXCEPTION 'Double booking prevented: table % has overlapping reservations', NEW.table_number;
+END IF;
+
+RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS trg_no_double_booking_ins ON frontstaff_managed_reservations;
+CREATE CONSTRAINT TRIGGER trg_no_double_booking_ins
+AFTER INSERT ON frontstaff_managed_reservations
+DEFERRABLE INITIALLY DEFERRED
+FOR EACH ROW EXECUTE FUNCTION enforce_no_double_booking();
+
+DROP TRIGGER IF EXISTS trg_no_double_booking_upd ON frontstaff_managed_reservations;
+CREATE CONSTRAINT TRIGGER trg_no_double_booking_upd
+AFTER UPDATE ON frontstaff_managed_reservations
+                 DEFERRABLE INITIALLY DEFERRED
+                 FOR EACH ROW EXECUTE FUNCTION enforce_no_double_booking();
+
+CREATE INDEX IF NOT EXISTS fmr_table_idx ON frontstaff_managed_reservations (table_number);
+CREATE INDEX IF NOT EXISTS reservations_span_expr_gist
+    ON reservations USING gist (
+    tsrange(
+    datetime,
+    datetime + (COALESCE(stay_length, 2) * INTERVAL '1 hour'),
+    '[)'
+    )
+    );
+CREATE INDEX IF NOT EXISTS idx_payments_order      ON payments(order_id);
+CREATE INDEX IF NOT EXISTS idx_payments_created_at ON payments(created_at);
+
+
+CREATE OR REPLACE FUNCTION fmr_capacity_guard() RETURNS trigger AS $$
+DECLARE
+cap int;
+  party bigint;
+BEGIN
+SELECT seat_capacity INTO cap FROM tables WHERE table_number = NEW.table_number;
+SELECT number_of_people INTO party FROM reservations WHERE id = NEW.reservation_id;
+
+IF cap IS NULL OR party IS NULL THEN
+    RAISE EXCEPTION 'Invalid reservation % or table %', NEW.reservation_id, NEW.table_number;
+END IF;
+
+  IF party > cap THEN
+    RAISE EXCEPTION 'Party size % exceeds capacity % for table %',
+      party, cap, NEW.table_number;
+END IF;
+
+RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS trg_fmr_capacity_ins ON frontstaff_managed_reservations;
+CREATE TRIGGER trg_fmr_capacity_ins
+    BEFORE INSERT ON frontstaff_managed_reservations
+    FOR EACH ROW EXECUTE FUNCTION fmr_capacity_guard();
+
+DROP TRIGGER IF EXISTS trg_fmr_capacity_upd ON frontstaff_managed_reservations;
+CREATE TRIGGER trg_fmr_capacity_upd
+    BEFORE UPDATE ON frontstaff_managed_reservations
+    FOR EACH ROW EXECUTE FUNCTION fmr_capacity_guard();
+
+
+CREATE OR REPLACE FUNCTION payments_mark_order_paid() RETURNS trigger AS $$
+BEGIN
+UPDATE orders
+SET status = 'PAID'
+WHERE id = NEW.order_id;
+RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS trg_payments_mark_order_paid ON payments;
+CREATE TRIGGER trg_payments_mark_order_paid
+    AFTER INSERT ON payments
+    FOR EACH ROW EXECUTE FUNCTION payments_mark_order_paid();
+
+
+CREATE MATERIALIZED VIEW IF NOT EXISTS mv_payments_daily_channel AS
+WITH orders_channel AS (
+  SELECT
+    o.id AS order_id,
+    CASE
+      WHEN EXISTS (SELECT 1 FROM tab_orders t WHERE t.order_id = o.id) THEN 'TAB'
+      WHEN EXISTS (SELECT 1 FROM online_orders oo WHERE oo.order_id = o.id) THEN 'ONLINE'
+      ELSE 'UNKNOWN'
+    END AS channel
+  FROM orders o
+)
+SELECT
+    (date_trunc('day', p.created_at))::date AS day,
+  oc.channel,
+  COUNT(DISTINCT p.order_id)            AS paid_orders_cnt,
+  SUM(p.amount)::numeric(14,2)          AS revenue,
+  SUM(p.tip_amount)::numeric(14,2)      AS tip_total
+FROM payments p
+    JOIN orders_channel oc ON oc.order_id = p.order_id
+GROUP BY (date_trunc('day', p.created_at))::date, oc.channel;
+
+CREATE UNIQUE INDEX IF NOT EXISTS ux_mv_payments_daily_channel
+    ON mv_payments_daily_channel (day, channel);
+
+REFRESH MATERIALIZED VIEW mv_payments_daily_channel;
+
+
+-- DML
+INSERT INTO users(id, email, password, phone_number, street, city)
+VALUES
+    (1, 'test@hotmail.com', 'password1', '070003005', 'Mladinska 3', 'Strumica'),
+    (2, 'test2@hotmail.com', 'password2', '070001002', 'Marsal Tito 10', 'Strumica'),
+    (3, 'test3@hotmail.com', 'password1', '070003003', 'Mladinska 5', 'Strumica'),
+    (4, 'test4@hotmail.com', 'password2', '070004004', 'Marsal Tito 11', 'Strumica'),
+    (5, 'test5@hotmail.com', 'password1', '070005005', 'Mladinska 12', 'Strumica');
+
+INSERT INTO employees(user_id, net_salary, gross_salary)
+VALUES
+    (1, 30000, 40000),
+    (3, 50000, 62000),
+    (4, 35000, 46000),
+    (5, 28000, 37000);
+
+INSERT INTO managers(employee_id)
+VALUES
+    (3);
+
+INSERT INTO staff_roles(id, name)
+VALUES
+    (1, 'Server'),
+    (2, 'Chef'),
+    (3, 'Bartender'),
+    (4, 'Hostess');
+
+INSERT INTO front_staff(employee_id, tip_percent, staff_role_id)
+VALUES
+    (1, .4, 1),
+    (5, 0.1, 4);
+
+INSERT INTO back_staff(employee_id, staff_role_id)
+VALUES
+    (4, 2);
+
+INSERT INTO customers(user_id)
+VALUES
+    (2);
+
+INSERT INTO shifts (id, date, start_time, end_time, manager_id)
+VALUES
+    (1, current_date, '09:00:00', '17:00:00', 3);
+
+INSERT INTO assignments(id, clock_in_time, clock_out_time, manager_id, employee_id, shift_id)
+VALUES
+    (1, NULL, NULL, 3, 1, 1);
+
+INSERT INTO tables(table_number, seat_capacity)
+VALUES
+    (1, 4),
+    (2, 8);
+
+INSERT INTO  reservations(id, user_id, creation_timestamp, datetime, stay_length, number_of_people)
+VALUES
+    (1, 2, now(), now(), NULL, 4);
+
+INSERT INTO frontstaff_managed_reservations(id, reservation_id, front_staff_id, table_number)
+VALUES
+    (1, 1, 5, 1);
+
+INSERT INTO categories(id, name)
+VALUES
+    (1, 'Drinks'),
+    (2, 'Appetizers'),
+    (3, 'Entrees');
+
+INSERT INTO products(id, name, description, price, category_id, manage_inventory, tax_class)
+VALUES
+    (1, 'Coca Cola', 'A classic carbonated soft drink.', 100, 1, TRUE, 'A'),
+    (2, 'Pomfrit so sirenje', 'Crispy french fries topped with melted cheese.', 250, 2, FALSE, 'A');
+
+INSERT INTO inventories(product_id, quantity)
+VALUES
+    (1, 100);
+
+INSERT INTO orders(id, status, datetime)
+VALUES
+    (1, 'PENDING', '2025-01-05 10:00:00'),
+    (2, 'ACCEPTED', '2025-01-05 10:00:00'),
+    (3, 'CONFIRMED', '2025-01-05 11:00:00');
+
+INSERT INTO order_items (id, order_id, product_id, is_processed, quantity, price)
+SELECT 1, 1, 1, TRUE, 3, price FROM products WHERE id = 1
+UNION ALL
+SELECT 2, 1, 2, FALSE, 1, price FROM products WHERE id = 2
+UNION ALL
+SELECT 3, 3, 2, FALSE, 2, price FROM products WHERE id = 2
+UNION ALL
+SELECT 4, 3, 1, FALSE, 2, price FROM products WHERE id = 1;
+
+INSERT INTO tab_orders(order_id, front_staff_id, table_number)
+VALUES
+    (1, 1, 1);
+
+INSERT INTO online_orders(order_id, delivery_address, customer_id)
+VALUES
+    (3, 'Leninova 5', 2);
+
+INSERT INTO payments(id, order_id, amount, payment_type, tip_amount)
+VALUES
+    (1, 3, 700, 'cash', 10);
+
+COMMIT;
Index: backend/docker-compose.yml
===================================================================
--- backend/docker-compose.yml	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/docker-compose.yml	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,18 @@
+version: '3.8'
+
+services:
+  db:
+    image: postgres:15.5
+    restart: always
+    environment:
+      POSTGRES_USER: springuser
+      POSTGRES_PASSWORD: springpassword
+      POSTGRES_DB: spring_boot_db
+    volumes:
+      - db_data:/var/lib/postgresql/data
+      - ./01.init.sql:/docker-entrypoint-initdb.d/init.sql
+    ports:
+      - "5435:5432"
+
+volumes:
+  db_data:
Index: backend/mvnw
===================================================================
--- backend/mvnw	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/mvnw	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,259 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.3.2
+#
+# Optional ENV vars
+# -----------------
+#   JAVA_HOME - location of a JDK home dir, required when download maven via java source
+#   MVNW_REPOURL - repo url base for downloading maven distribution
+#   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+#   MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
+# ----------------------------------------------------------------------------
+
+set -euf
+[ "${MVNW_VERBOSE-}" != debug ] || set -x
+
+# OS specific support.
+native_path() { printf %s\\n "$1"; }
+case "$(uname)" in
+CYGWIN* | MINGW*)
+  [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
+  native_path() { cygpath --path --windows "$1"; }
+  ;;
+esac
+
+# set JAVACMD and JAVACCMD
+set_java_home() {
+  # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
+  if [ -n "${JAVA_HOME-}" ]; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+      JAVACCMD="$JAVA_HOME/jre/sh/javac"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+      JAVACCMD="$JAVA_HOME/bin/javac"
+
+      if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
+        echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
+        echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
+        return 1
+      fi
+    fi
+  else
+    JAVACMD="$(
+      'set' +e
+      'unset' -f command 2>/dev/null
+      'command' -v java
+    )" || :
+    JAVACCMD="$(
+      'set' +e
+      'unset' -f command 2>/dev/null
+      'command' -v javac
+    )" || :
+
+    if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
+      echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
+      return 1
+    fi
+  fi
+}
+
+# hash string like Java String::hashCode
+hash_string() {
+  str="${1:-}" h=0
+  while [ -n "$str" ]; do
+    char="${str%"${str#?}"}"
+    h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
+    str="${str#?}"
+  done
+  printf %x\\n $h
+}
+
+verbose() { :; }
+[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
+
+die() {
+  printf %s\\n "$1" >&2
+  exit 1
+}
+
+trim() {
+  # MWRAPPER-139:
+  #   Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
+  #   Needed for removing poorly interpreted newline sequences when running in more
+  #   exotic environments such as mingw bash on Windows.
+  printf "%s" "${1}" | tr -d '[:space:]'
+}
+
+# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
+while IFS="=" read -r key value; do
+  case "${key-}" in
+  distributionUrl) distributionUrl=$(trim "${value-}") ;;
+  distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
+  esac
+done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+
+case "${distributionUrl##*/}" in
+maven-mvnd-*bin.*)
+  MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
+  case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
+  *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
+  :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
+  :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
+  :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
+  *)
+    echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
+    distributionPlatform=linux-amd64
+    ;;
+  esac
+  distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
+  ;;
+maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
+*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+esac
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
+[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
+distributionUrlName="${distributionUrl##*/}"
+distributionUrlNameMain="${distributionUrlName%.*}"
+distributionUrlNameMain="${distributionUrlNameMain%-bin}"
+MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
+MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
+
+exec_maven() {
+  unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
+  exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
+}
+
+if [ -d "$MAVEN_HOME" ]; then
+  verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+  exec_maven "$@"
+fi
+
+case "${distributionUrl-}" in
+*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
+*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
+esac
+
+# prepare tmp dir
+if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
+  clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
+  trap clean HUP INT TERM EXIT
+else
+  die "cannot create temp dir"
+fi
+
+mkdir -p -- "${MAVEN_HOME%/*}"
+
+# Download and Install Apache Maven
+verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+verbose "Downloading from: $distributionUrl"
+verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+# select .zip or .tar.gz
+if ! command -v unzip >/dev/null; then
+  distributionUrl="${distributionUrl%.zip}.tar.gz"
+  distributionUrlName="${distributionUrl##*/}"
+fi
+
+# verbose opt
+__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
+[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
+
+# normalize http auth
+case "${MVNW_PASSWORD:+has-password}" in
+'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+esac
+
+if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
+  verbose "Found wget ... using wget"
+  wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
+elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
+  verbose "Found curl ... using curl"
+  curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
+elif set_java_home; then
+  verbose "Falling back to use Java to download"
+  javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
+  targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
+  cat >"$javaSource" <<-END
+	public class Downloader extends java.net.Authenticator
+	{
+	  protected java.net.PasswordAuthentication getPasswordAuthentication()
+	  {
+	    return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
+	  }
+	  public static void main( String[] args ) throws Exception
+	  {
+	    setDefault( new Downloader() );
+	    java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
+	  }
+	}
+	END
+  # For Cygwin/MinGW, switch paths to Windows format before running javac and java
+  verbose " - Compiling Downloader.java ..."
+  "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
+  verbose " - Running Downloader.java ..."
+  "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
+fi
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+if [ -n "${distributionSha256Sum-}" ]; then
+  distributionSha256Result=false
+  if [ "$MVN_CMD" = mvnd.sh ]; then
+    echo "Checksum validation is not supported for maven-mvnd." >&2
+    echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+    exit 1
+  elif command -v sha256sum >/dev/null; then
+    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
+      distributionSha256Result=true
+    fi
+  elif command -v shasum >/dev/null; then
+    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
+      distributionSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
+    echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+    exit 1
+  fi
+  if [ $distributionSha256Result = false ]; then
+    echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
+    echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+# unzip and move
+if command -v unzip >/dev/null; then
+  unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
+else
+  tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
+fi
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+clean || :
+exec_maven "$@"
Index: backend/mvnw.cmd
===================================================================
--- backend/mvnw.cmd	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/mvnw.cmd	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,149 @@
+<# : batch portion
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.3.2
+@REM
+@REM Optional ENV vars
+@REM   MVNW_REPOURL - repo url base for downloading maven distribution
+@REM   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM   MVNW_VERBOSE - true: enable verbose log; others: silence the output
+@REM ----------------------------------------------------------------------------
+
+@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
+@SET __MVNW_CMD__=
+@SET __MVNW_ERROR__=
+@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
+@SET PSModulePath=
+@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
+  IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
+)
+@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
+@SET __MVNW_PSMODULEP_SAVE=
+@SET __MVNW_ARG0_NAME__=
+@SET MVNW_USERNAME=
+@SET MVNW_PASSWORD=
+@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
+@echo Cannot start maven from wrapper >&2 && exit /b 1
+@GOTO :EOF
+: end batch / begin powershell #>
+
+$ErrorActionPreference = "Stop"
+if ($env:MVNW_VERBOSE -eq "true") {
+  $VerbosePreference = "Continue"
+}
+
+# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
+$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
+if (!$distributionUrl) {
+  Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+}
+
+switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
+  "maven-mvnd-*" {
+    $USE_MVND = $true
+    $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
+    $MVN_CMD = "mvnd.cmd"
+    break
+  }
+  default {
+    $USE_MVND = $false
+    $MVN_CMD = $script -replace '^mvnw','mvn'
+    break
+  }
+}
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
+if ($env:MVNW_REPOURL) {
+  $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+  $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
+}
+$distributionUrlName = $distributionUrl -replace '^.*/',''
+$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
+$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
+if ($env:MAVEN_USER_HOME) {
+  $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
+}
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
+
+if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
+  Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+  Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+  exit $?
+}
+
+if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
+  Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
+}
+
+# prepare tmp dir
+$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
+$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
+$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
+trap {
+  if ($TMP_DOWNLOAD_DIR.Exists) {
+    try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+    catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+  }
+}
+
+New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
+
+# Download and Install Apache Maven
+Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+Write-Verbose "Downloading from: $distributionUrl"
+Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+$webclient = New-Object System.Net.WebClient
+if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
+  $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
+}
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
+if ($distributionSha256Sum) {
+  if ($USE_MVND) {
+    Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
+  }
+  Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
+  if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
+    Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
+  }
+}
+
+# unzip and move
+Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
+try {
+  Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
+} catch {
+  if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
+    Write-Error "fail to move MAVEN_HOME"
+  }
+} finally {
+  try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+  catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+}
+
+Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
Index: backend/pom.xml
===================================================================
--- backend/pom.xml	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/pom.xml	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.5.3</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <groupId>finki.db</groupId>
+    <artifactId>Tasty_Tabs</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>Tasty Tabs</name>
+    <description>Tasty Tabs</description>
+
+    <properties>
+        <java.version>17</java.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jdbc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.flywaydb</groupId>
+            <artifactId>flyway-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.flywaydb</groupId>
+            <artifactId>flyway-database-postgresql</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- ✅ Fixed Lombok dependency -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.34</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+            <version>2.3.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-api</artifactId>
+            <version>0.11.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-impl</artifactId>
+            <version>0.11.2</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-jackson</artifactId>
+            <version>0.11.2</version>
+            <scope>runtime</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!-- ✅ Added version and ensured Lombok is included in annotation processing -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.11.0</version>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.springframework.boot</groupId>
+                            <artifactId>spring-boot-configuration-processor</artifactId>
+                        </path>
+                        <path>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                            <version>1.18.34</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
Index: backend/src/main/java/finki/db/tasty_tabs/TastyTabsApplication.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/TastyTabsApplication.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/TastyTabsApplication.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class TastyTabsApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(TastyTabsApplication.class, args);
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/config/OpenApiConfig.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/config/OpenApiConfig.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/config/OpenApiConfig.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,50 @@
+package finki.db.tasty_tabs.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import io.swagger.v3.core.jackson.ModelResolver;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.media.StringSchema;
+import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+import io.swagger.v3.oas.models.servers.Server;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.springdoc.core.customizers.OpenApiCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+@Configuration
+public class OpenApiConfig {
+
+    @Bean
+    public ModelResolver modelResolver(ObjectMapper objectMapper) {
+        return new ModelResolver(objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE));
+    }
+
+    @Bean
+    public OpenApiCustomizer globalHeaderCustomizer() {
+        return openApi -> {
+            // No action is performed here, effectively removing the global parameter
+        };
+    }
+
+    @Bean
+    public OpenAPI customOpenAPI() {
+        return new OpenAPI()
+                .components(new Components()
+                        .addSecuritySchemes("bearerAuth",
+                                new SecurityScheme()
+                                        .type(SecurityScheme.Type.HTTP)
+                                        .scheme("bearer")
+                                        .bearerFormat("JWT")
+                        )
+                )
+                .addSecurityItem(new SecurityRequirement().addList("bearerAuth"))
+                .addServersItem(new Server().url("http://localhost:8080").description("Local server"));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/config/WebConfig.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/config/WebConfig.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/config/WebConfig.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,22 @@
+package finki.db.tasty_tabs.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+    public WebConfig() {
+    }
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOrigins("*")
+                .allowedMethods("*")
+                .allowedHeaders("*")
+                .allowCredentials(false)
+                .maxAge(3600);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Assignment.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Assignment.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Assignment.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,104 @@
+package finki.db.tasty_tabs.entity;
+
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * Entity: Assignment
+ * Description: Represents shift assignment for each employee.
+ */
+@Entity
+@Table(name = "assignments")
+@Data
+@NoArgsConstructor
+public class Assignment {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "clock_in_time")
+    private LocalDateTime clockInTime;
+
+    @Column(name = "clock_out_time")
+    private LocalDateTime clockOutTime;
+
+    @ManyToOne
+    @JoinColumn(name = "manager_id", referencedColumnName = "employee_id", nullable = false)
+    private Manager manager;
+
+    @ManyToOne
+    @JoinColumn(name = "employee_id", referencedColumnName = "user_id", nullable = false)
+    private Employee employee;
+
+    @ManyToOne
+    @JoinColumn(name = "shift_id", referencedColumnName = "id", nullable = false)
+    private Shift shift;
+
+    public Assignment(LocalDateTime clockInTime, LocalDateTime clockOutTime, Employee employee, Shift shift) {
+        this.clockInTime = clockInTime;
+        this.clockOutTime = clockOutTime;
+        this.employee = employee;
+        this.shift = shift;
+    }
+
+    public Assignment(LocalDateTime clockInTime, LocalDateTime clockOutTime, Manager manager, Employee employee, Shift shift) {
+        this.clockInTime = clockInTime;
+        this.clockOutTime = clockOutTime;
+        this.manager = manager;
+        this.employee = employee;
+        this.shift = shift;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public LocalDateTime getClockInTime() {
+        return clockInTime;
+    }
+
+    public void setClockInTime(LocalDateTime clockInTime) {
+        this.clockInTime = clockInTime;
+    }
+
+    public LocalDateTime getClockOutTime() {
+        return clockOutTime;
+    }
+
+    public void setClockOutTime(LocalDateTime clockOutTime) {
+        this.clockOutTime = clockOutTime;
+    }
+
+    public Manager getManager() {
+        return manager;
+    }
+
+    public void setManager(Manager manager) {
+        this.manager = manager;
+    }
+
+    public Employee getEmployee() {
+        return employee;
+    }
+
+    public void setEmployee(Employee employee) {
+        this.employee = employee;
+    }
+
+    public Shift getShift() {
+        return shift;
+    }
+
+    public void setShift(Shift shift) {
+        this.shift = shift;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/BackStaff.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/BackStaff.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/BackStaff.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,24 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+/**
+ * Entity: BackStaff
+ * Description: A disjoint specialization of the Employee entity for back-office staff members.
+ */
+@Entity
+@Table(name = "back_staff")
+@Data
+@NoArgsConstructor
+@PrimaryKeyJoinColumn(name = "employee_id", referencedColumnName = "user_id")
+public class BackStaff extends Employee {
+
+    @ManyToOne
+    @JoinColumn(name = "staff_role_id", referencedColumnName = "id")
+    private StaffRole staffRole;
+
+    public UserType getUserType() {
+        return UserType.BACK_STAFF;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Category.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Category.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Category.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,37 @@
+package finki.db.tasty_tabs.entity;
+
+import com.fasterxml.jackson.annotation.JsonManagedReference;
+import jakarta.persistence.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: Category
+ */
+@Entity
+@Table(name = "categories")
+@Data
+@NoArgsConstructor
+public class Category {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(nullable = false, unique = true)
+    private String name;
+
+    @Column(name = "is_available")
+    private Boolean isAvailable;
+
+    @OneToMany(mappedBy = "category", fetch = FetchType.LAZY)
+    @JsonManagedReference
+    private List<Product> products;
+
+    public Category(String name, Boolean isAvailable) {
+        this.name = name;
+        this.isAvailable = isAvailable;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Customer.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Customer.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Customer.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,27 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: Customer
+ * Description: Represents customers in the system. Inherits from User.
+ */
+@Entity
+@Table(name = "customers")
+@Data
+@NoArgsConstructor
+@PrimaryKeyJoinColumn(name = "user_id") // Links to the User table
+public class Customer extends User {
+    
+    // Relationship for online orders placed by this customer
+    @OneToMany(mappedBy = "customer")
+    private List<OnlineOrder> onlineOrders;
+
+    public UserType getUserType() {
+        return UserType.CUSTOMER;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Employee.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Employee.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Employee.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,72 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: Employee
+ * Description: Represents employees of the system. Inherits from User.
+ */
+@Entity
+@Table(name = "employees")
+@Data
+@PrimaryKeyJoinColumn(name = "user_id") // Links to the User table
+public class Employee extends User {
+
+    @Column(name = "net_salary", nullable = false)
+    private Double netSalary;
+
+    @Column(name = "gross_salary", nullable = false)
+    private Double grossSalary;
+
+    // Relationship for assignments given to this employee
+    @OneToMany(mappedBy = "employee")
+    private List<Assignment> assignments;
+
+    public Employee() {
+        super();
+    }
+    public Employee(Double netSalary, Double grossSalary) {
+        super();
+        this.netSalary = netSalary;
+        this.grossSalary = grossSalary;
+    }
+
+    public Employee(String email, String street, String city, String phoneNumber, Double netSalary, Double grossSalary, List<Assignment> assignments) {
+        super(email, street, city, phoneNumber);
+        this.netSalary = netSalary;
+        this.grossSalary = grossSalary;
+        this.assignments = assignments;
+    }
+
+    public Double getNetSalary() {
+        return netSalary;
+    }
+
+    public List<Assignment> getAssignments() {
+        return assignments;
+    }
+
+    public void setAssignments(List<Assignment> assignments) {
+        this.assignments = assignments;
+    }
+
+    public void setNetSalary(Double netSalary) {
+        this.netSalary = netSalary;
+    }
+
+    public Double getGrossSalary() {
+        return grossSalary;
+    }
+
+    public void setGrossSalary(Double grossSalary) {
+        this.grossSalary = grossSalary;
+    }
+
+    public UserType getUserType(){
+        return UserType.EMPLOYEE;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/EmployeeType.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/EmployeeType.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/EmployeeType.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,5 @@
+package finki.db.tasty_tabs.entity;
+
+public enum EmployeeType {
+    MANAGER, FRONT_STAFF, BACK_STAFF
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/FrontStaff.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/FrontStaff.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/FrontStaff.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,69 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: FrontStaff
+ * Description: A disjoint specialization of the Employee entity for front-facing staff members.
+ */
+@Entity
+@Table(name = "front_staff")
+@Data
+@NoArgsConstructor
+@PrimaryKeyJoinColumn(name = "employee_id", referencedColumnName = "user_id")
+public class FrontStaff extends Employee {
+
+    @Column(name = "tip_percent")
+    private Double tipPercent;
+
+    @ManyToOne
+    @JoinColumn(name = "staff_role_id", referencedColumnName = "id")
+    private StaffRole staffRole;
+
+    // Relationship for tab orders handled by this front staff member
+    @OneToMany(mappedBy = "frontStaff")
+    private List<TabOrder> tabOrders;
+
+    @OneToMany(mappedBy = "frontStaff")
+    private List<ReservationManagedFrontStaff> managedReservations;
+
+    public Double getTipPercent() {
+        return tipPercent;
+    }
+
+    public void setTipPercent(Double tipPercent) {
+        this.tipPercent = tipPercent;
+    }
+
+    public StaffRole getStaffRole() {
+        return staffRole;
+    }
+
+    public void setStaffRole(StaffRole staffRole) {
+        this.staffRole = staffRole;
+    }
+
+    public List<TabOrder> getTabOrders() {
+        return tabOrders;
+    }
+
+    public void setTabOrders(List<TabOrder> tabOrders) {
+        this.tabOrders = tabOrders;
+    }
+
+    public List<ReservationManagedFrontStaff> getManagedReservations() {
+        return managedReservations;
+    }
+
+    public void setManagedReservations(List<ReservationManagedFrontStaff> managedReservations) {
+        this.managedReservations = managedReservations;
+    }
+
+    public UserType getUserType() {
+        return UserType.FRONT_STAFF;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Inventory.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Inventory.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Inventory.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,69 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+/**
+ * Entity: Inventory
+ * Description: Tracks product quantities and restocking levels.
+ */
+@Entity
+@Table(name = "inventories")
+@Data
+@NoArgsConstructor
+public class Inventory {
+
+    @Id
+    @Column(name = "product_id")
+    private Long productId;
+
+    @OneToOne(fetch = FetchType.LAZY)
+    @MapsId
+    @JoinColumn(name = "product_id")
+    private Product product;
+
+    @Column(name = "quantity", nullable = false)
+    private Integer quantity;
+
+    @Column(name = "restock_level")
+    private Integer restockLevel;
+
+    public Inventory(Product product, Integer quantity, Integer restockLevel) {
+        this.product = product;  // @MapsId ќе го земе id-то
+        this.quantity = quantity;
+        this.restockLevel = restockLevel;
+    }
+
+
+    public Long getProductId() {
+        return productId;
+    }
+
+    public void setProductId(Long productId) {
+        this.productId = productId;
+    }
+
+    public Product getProduct() {
+        return product;
+    }
+
+    public void setProduct(Product product) {
+        this.product = product;
+    }
+
+    public Integer getQuantity() {
+        return quantity;
+    }
+
+    public void setQuantity(Integer quantity) {
+        this.quantity = quantity;
+    }
+
+    public Integer getRestockLevel() {
+        return restockLevel;
+    }
+
+    public void setRestockLevel(Integer restockLevel) {
+        this.restockLevel = restockLevel;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Manager.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Manager.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Manager.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,32 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: Manager
+ * Description: A disjoint specialization of the Employee entity for managers.
+ */
+@Entity
+@Table(name = "managers")
+@Data
+@NoArgsConstructor
+@PrimaryKeyJoinColumn(name = "employee_id", referencedColumnName = "user_id")
+public class Manager extends Employee {
+
+    // Relationship for shifts created by this manager
+    @OneToMany(mappedBy = "manager")
+    private List<Shift> createdShifts;
+
+    // Relationship for assignments created by this manager
+    @OneToMany(mappedBy = "manager")
+    private List<Assignment> createdAssignments;
+
+
+    public UserType getUserType() {
+        return UserType.MANAGER;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/OnlineOrder.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/OnlineOrder.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/OnlineOrder.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,39 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+/**
+ * Entity: OnlineOrder
+ * Description: Represents orders made online by customers.
+ */
+@Entity
+@Table(name = "online_orders")
+@Data
+@NoArgsConstructor
+@PrimaryKeyJoinColumn(name = "order_id")
+public class OnlineOrder extends Order {
+
+    @ManyToOne
+    @JoinColumn(name = "customer_id", referencedColumnName = "user_id", nullable = false)
+    private Customer customer;
+
+    @Column(name = "delivery_address", nullable = false)
+    private String deliveryAddress;
+
+    public Customer getCustomer() {
+        return customer;
+    }
+
+    public void setCustomer(Customer customer) {
+        this.customer = customer;
+    }
+
+    public String getDeliveryAddress() {
+        return deliveryAddress;
+    }
+
+    public void setDeliveryAddress(String deliveryAddress) {
+        this.deliveryAddress = deliveryAddress;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Order.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Order.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Order.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,77 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Entity: Order
+ * Description: Represents a customer's order in the system.
+ */
+@Entity
+@Table(name = "orders") // "order" is a reserved keyword
+@Data
+@NoArgsConstructor
+@Inheritance(strategy = InheritanceType.JOINED)
+public class Order {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "datetime", nullable = false)
+    private LocalDateTime timestamp;
+
+    @Column(name = "status")
+    private String status;
+
+    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
+    private List<OrderItem> orderItems = new ArrayList<>();
+
+    @OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
+    private Payment payment;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public LocalDateTime getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(LocalDateTime timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public List<OrderItem> getOrderItems() {
+        return orderItems != null ? orderItems : new ArrayList<OrderItem>();
+    }
+
+    public void setOrderItems(List<OrderItem> orderItems) {
+        this.orderItems = orderItems;
+    }
+
+    public Payment getPayment() {
+        return payment;
+    }
+
+    public void setPayment(Payment payment) {
+        this.payment = payment;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/OrderItem.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/OrderItem.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/OrderItem.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,42 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * Entity: OrderItem
+ * Description: Represents items in a customer's order.
+ */
+@Entity
+@Table(name = "order_items")
+@Data
+@NoArgsConstructor
+public class OrderItem {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "quantity", nullable = false)
+    private Integer quantity;
+
+    @Column(name = "price", nullable = false)
+    private Double price;
+
+    @Column(name = "is_processed")
+    private Boolean isProcessed;
+
+    @Column(name = "created_at", nullable = false)
+    private LocalDateTime timestamp;
+
+    @ManyToOne
+    @JoinColumn(name = "product_id", referencedColumnName = "id", nullable = false)
+    private Product product;
+
+    @ManyToOne
+    @JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false)
+    private Order order;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Payment.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Payment.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Payment.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,87 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * Entity: Payment
+ * Description: Represents payments for orders.
+ */
+@Entity
+@Table(name = "payments")
+@Data
+@NoArgsConstructor
+public class Payment {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "tip_amount")
+    private Double tipAmount;
+
+    @Column(name = "created_at", nullable = false)
+    private LocalDateTime timestamp;
+
+    @Column(name = "payment_type", nullable = false)
+    private String paymentType;
+
+    @Column(name = "amount", nullable = false)
+    private Double amount;
+
+    @OneToOne
+    @JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false, unique = true)
+    private Order order;
+
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Double getTipAmount() {
+        return tipAmount;
+    }
+
+    public void setTipAmount(Double tipAmount) {
+        this.tipAmount = tipAmount;
+    }
+
+    public LocalDateTime getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(LocalDateTime timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getPaymentType() {
+        return paymentType;
+    }
+
+    public void setPaymentType(String paymentType) {
+        this.paymentType = paymentType;
+    }
+
+    public Double getAmount() {
+        return amount;
+    }
+
+    public void setAmount(Double amount) {
+        this.amount = amount;
+    }
+
+    public Order getOrder() {
+        return order;
+    }
+
+    public void setOrder(Order order) {
+        this.order = order;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Product.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Product.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Product.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,49 @@
+package finki.db.tasty_tabs.entity;
+
+import com.fasterxml.jackson.annotation.JsonBackReference;
+import jakarta.persistence.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: Product
+ */
+@Entity
+@Table(name = "products")
+@Data
+@NoArgsConstructor
+public class Product {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(nullable = false)
+    private String name;
+
+    @Column(nullable = false)
+    private Double price;
+
+    @Column(name = "tax_class")
+    private String taxClass;
+
+//    @Column(length = 1024)
+    @Transient
+    private String description = "";
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "category_id", nullable = false)
+    @JsonBackReference
+    private Category category;
+
+    @Column(name = "manage_inventory")
+    private Boolean manageInventory;
+
+    @OneToOne(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+    private Inventory inventory;
+
+    @OneToMany(mappedBy = "product")
+    private List<OrderItem> orderItems;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Reservation.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Reservation.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Reservation.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,98 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * Entity: Reservation
+ * Description: Represents reservations made by users.
+ */
+@Entity
+@Table(name = "reservations")
+@Data
+@NoArgsConstructor
+public class Reservation {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "stay_length")
+    private Integer stayLength;
+
+    @Column(name = "datetime", nullable = false)
+    private LocalDateTime datetime;
+
+    @Column(name = "creation_timestamp", nullable = false)
+    private LocalDateTime creationTimestamp;
+
+    @Column(name = "number_of_people", nullable = false)
+    private Integer numberOfPeople;
+
+    @ManyToOne
+    @JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)
+    private User user;
+
+    @OneToMany(mappedBy = "reservation")
+    private List<ReservationManagedFrontStaff> managedReservations;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Integer getStayLength() {
+        return stayLength;
+    }
+
+    public void setStayLength(Integer stayLength) {
+        this.stayLength = stayLength;
+    }
+
+    public LocalDateTime getDatetime() {
+        return datetime;
+    }
+
+    public void setDatetime(LocalDateTime datetime) {
+        this.datetime = datetime;
+    }
+
+    public LocalDateTime getCreationTimestamp() {
+        return creationTimestamp;
+    }
+
+    public void setCreationTimestamp(LocalDateTime creationTimestamp) {
+        this.creationTimestamp = creationTimestamp;
+    }
+
+    public Integer getNumberOfPeople() {
+        return numberOfPeople;
+    }
+
+    public void setNumberOfPeople(Integer numberOfPeople) {
+        this.numberOfPeople = numberOfPeople;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+
+    public List<ReservationManagedFrontStaff> getManagedReservations() {
+        return managedReservations;
+    }
+
+    public void setManagedReservations(List<ReservationManagedFrontStaff> managedReservations) {
+        this.managedReservations = managedReservations;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/ReservationManagedFrontStaff.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/ReservationManagedFrontStaff.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/ReservationManagedFrontStaff.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,30 @@
+package finki.db.tasty_tabs.entity;// finki.db.tasty_tabs.entity.ReservationManagedFrontStaff
+import jakarta.persistence.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import finki.db.tasty_tabs.entity.composite_keys.ReservationManagedFrontStaffId;
+
+@Entity
+@Table(name = "frontstaff_managed_reservations")
+@Data
+@NoArgsConstructor
+public class ReservationManagedFrontStaff {
+
+    @EmbeddedId
+    private ReservationManagedFrontStaffId id;
+
+    @ManyToOne
+    @MapsId("reservationId")
+    @JoinColumn(name = "reservation_id", referencedColumnName = "id")
+    private Reservation reservation;
+
+    @ManyToOne
+    @MapsId("frontstaffId")
+    @JoinColumn(name = "front_staff_id", referencedColumnName = "employee_id")
+    private FrontStaff frontStaff;
+
+    @ManyToOne
+    @MapsId("tableNumber")
+    @JoinColumn(name = "table_number", referencedColumnName = "table_number")
+    private RestaurantTable restaurantTable;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/RestaurantTable.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/RestaurantTable.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/RestaurantTable.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,36 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: Table
+ * Description: Represents dining tables in the system.
+ */
+@Entity
+@Table(name = "tables") // "table" is a reserved keyword
+@Data
+@NoArgsConstructor
+public class RestaurantTable {
+
+    @Id
+    @Column(name = "table_number")
+    private Long tableNumber;
+
+    @Column(name = "seat_capacity", nullable = false)
+    private Integer seatCapacity;
+
+    @OneToMany(mappedBy = "restaurantTable")
+    private List<TabOrder> tabOrders;
+
+    @OneToMany(mappedBy = "restaurantTable")
+    private List<ReservationManagedFrontStaff> managedReservations;
+
+    public RestaurantTable(Long tableNumber, Integer seatCapacity) {
+        this.tableNumber=tableNumber;
+        this.seatCapacity=seatCapacity;
+    }
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/entity/Shift.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/Shift.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/Shift.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,102 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Entity: Shift
+ * Description: Represents a work shift in the system.
+ */
+@Entity
+@Table(name = "shifts")
+@Data
+@NoArgsConstructor
+public class Shift {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "date", nullable = false)
+    private LocalDate date;
+
+    @Column(name = "start_time", nullable = false)
+    private LocalDateTime start;
+
+    @Column(name = "end_time", nullable = false)
+    private LocalDateTime end;
+
+    @ManyToOne
+    @JoinColumn(name = "manager_id", referencedColumnName = "employee_id", nullable = false)
+    private Manager manager;
+
+    @OneToMany(mappedBy = "shift")
+    private List<Assignment> assignments = new ArrayList<>();
+
+    public Shift(LocalDate date, LocalDateTime start, LocalDateTime end, Manager manager) {
+        this.date = date;
+        this.start = start;
+        this.end = end;
+        this.manager = manager;
+    }
+
+    public Shift(LocalDate date, LocalDateTime start, LocalDateTime end) {
+        this.date = date;
+        this.start = start;
+        this.end = end;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public LocalDate getDate() {
+        return date;
+    }
+
+    public void setDate(LocalDate date) {
+        this.date = date;
+    }
+
+    public LocalDateTime getStart() {
+        return start;
+    }
+
+    public void setStart(LocalDateTime start) {
+        this.start = start;
+    }
+
+    public LocalDateTime getEnd() {
+        return end;
+    }
+
+    public void setEnd(LocalDateTime end) {
+        this.end = end;
+    }
+
+    public Manager getManager() {
+        return manager;
+    }
+
+    public void setManager(Manager manager) {
+        this.manager = manager;
+    }
+
+    public List<Assignment> getAssignments() {
+        return assignments;
+    }
+
+    public void setAssignments(List<Assignment> assignments) {
+        this.assignments = assignments;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/StaffRole.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/StaffRole.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/StaffRole.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,31 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Entity: StaffRole
+ * Description: Defines roles for staff members.
+ */
+@Entity
+@Table(name = "staff_roles")
+@Data
+@NoArgsConstructor
+public class StaffRole {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "name", nullable = false, unique = true)
+    private String name;
+
+    @OneToMany(mappedBy = "staffRole")
+    private List<FrontStaff> frontStaffs;
+
+    @OneToMany(mappedBy = "staffRole")
+    private List<BackStaff> backStaffs;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/TabOrder.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/TabOrder.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/TabOrder.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,40 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+/**
+ * Entity: TabOrder
+ * Description: Represents orders made at a specific table.
+ */
+@Entity
+@Table(name = "tab_orders")
+@Data
+@NoArgsConstructor
+@PrimaryKeyJoinColumn(name = "order_id")
+public class TabOrder extends Order {
+
+    @ManyToOne
+    @JoinColumn(name = "table_number", referencedColumnName = "table_number", nullable = false)
+    private RestaurantTable restaurantTable;
+
+    @ManyToOne
+    @JoinColumn(name = "front_staff_id", referencedColumnName = "employee_id", nullable = false)
+    private FrontStaff frontStaff;
+
+    public RestaurantTable getRestaurantTable() {
+        return restaurantTable;
+    }
+
+    public void setRestaurantTable(RestaurantTable restaurantTable) {
+        this.restaurantTable = restaurantTable;
+    }
+
+    public FrontStaff getFrontStaff() {
+        return frontStaff;
+    }
+
+    public void setFrontStaff(FrontStaff frontStaff) {
+        this.frontStaff = frontStaff;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/User.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/User.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/User.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,83 @@
+package finki.db.tasty_tabs.entity;
+import jakarta.persistence.*;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Entity: User
+ * Description: Contains main information about all users in the system.
+ */
+@Entity
+@Table(name = "users") // "user" is often a reserved keyword in SQL
+@Data
+@NoArgsConstructor
+@Inheritance(strategy = InheritanceType.JOINED) // Strategy to allow for Employee/Customer subtypes
+public class User {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "email", nullable = false, unique = true)
+    private String email;
+
+    @Column(name = "street")
+    private String street;
+
+    @Column(name = "city")
+    private String city;
+
+    @Column(name = "phone_number")
+    private String phoneNumber;
+
+    @Column(name = "password", nullable = false)
+    private String password;
+
+    // Relationship for Reservations made by a user (if they are a customer)
+    @OneToMany(mappedBy = "user")
+    private List<Reservation> reservations = new ArrayList<>();
+    public User(String email, String street, String city, String phoneNumber) {
+        this.email = email;
+        this.street = street;
+        this.city = city;
+        this.phoneNumber = phoneNumber;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    public void setPhoneNumber(String phoneNumber) {
+        this.phoneNumber = phoneNumber;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public void setReservations(List<Reservation> reservations) {
+        this.reservations = reservations;
+    }
+
+    public UserType getUserType() {
+        return UserType.USER;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/UserType.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/UserType.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/UserType.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.entity;
+
+public enum UserType {
+    CUSTOMER,
+    MANAGER,
+    FRONT_STAFF,
+    BACK_STAFF,
+    USER, EMPLOYEE
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/composite_keys/ReservationManagedFrontStaffId.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/composite_keys/ReservationManagedFrontStaffId.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/composite_keys/ReservationManagedFrontStaffId.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,40 @@
+package finki.db.tasty_tabs.entity.composite_keys;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import java.io.Serializable;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.util.Objects;
+
+@Embeddable
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ReservationManagedFrontStaffId implements Serializable {
+
+    @Column(name = "reservation_id")
+    private Long reservationId;
+
+    @Column(name = "front_staff_id")
+    private Long frontstaffId;
+
+    @Column(name = "table_number")
+    private Long tableNumber;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ReservationManagedFrontStaffId that = (ReservationManagedFrontStaffId) o;
+        return Objects.equals(reservationId, that.reservationId) &&
+                Objects.equals(frontstaffId, that.frontstaffId) &&
+                Objects.equals(tableNumber, that.tableNumber);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(reservationId, frontstaffId, tableNumber);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/AssignmentNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/AssignmentNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/AssignmentNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class AssignmentNotFoundException extends DomainException {
+
+    public AssignmentNotFoundException(Long id) {
+        super(String.format("Assignment with id %d doesnt exist",id));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/CategoryNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/CategoryNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/CategoryNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,11 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class CategoryNotFoundException extends DomainException {
+
+    public CategoryNotFoundException(String name) {
+        super(String.format("Category: %s doesnt exist",name));
+    }
+    public CategoryNotFoundException() {
+        super("Category doesnt exist");
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/DomainException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/DomainException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/DomainException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,7 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public abstract class DomainException extends RuntimeException {
+    public DomainException(String message) {
+        super(message);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/EmployeeNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/EmployeeNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/EmployeeNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class EmployeeNotFoundException extends DomainException {
+
+    public EmployeeNotFoundException(Long id) {
+        super(String.format("Employee with id %d doesnt exist",id));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/FrontStaffNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/FrontStaffNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/FrontStaffNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class FrontStaffNotFoundException extends DomainException {
+
+    public FrontStaffNotFoundException(Long id) {
+        super(String.format("FrontStaff with id %d doesnt exist",id));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/InvalidOrderTypeException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/InvalidOrderTypeException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/InvalidOrderTypeException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class InvalidOrderTypeException extends DomainException {
+
+    public InvalidOrderTypeException(String message) {
+        super(message);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderItemNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderItemNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderItemNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class OrderItemNotFoundException extends DomainException {
+
+    public OrderItemNotFoundException() {
+        super(String.format("OrderItem doesnt exist"));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class OrderNotFoundException extends DomainException {
+
+    public OrderNotFoundException(Long id) {
+        super(String.format("Order with id %d doesnt exist",id));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/PaymentNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/PaymentNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/PaymentNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class PaymentNotFoundException extends DomainException {
+
+    public PaymentNotFoundException(Long id) {
+        super(String.format("Payment with id %d doesnt exist",id));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class ProductNotFoundException extends DomainException {
+
+    public ProductNotFoundException(Long id) {
+        super(String.format("Product with id %d doesnt exist",id));
+    }
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotInStockException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotInStockException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotInStockException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class ProductNotInStockException extends DomainException {
+
+    public ProductNotInStockException(String name) {
+        super(String.format("Product: %s not in stock",name));
+    }
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ReservationNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ReservationNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ReservationNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class ReservationNotFoundException extends DomainException {
+
+    public ReservationNotFoundException(Long id) {
+        super(String.format("Reservation with id %d doesnt exist",id));
+    }
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ShiftNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ShiftNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/ShiftNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class ShiftNotFoundException extends DomainException {
+
+    public ShiftNotFoundException(Long id) {
+        super(String.format("Shift with id %d doesnt exist",id));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNotFoundException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNotFoundException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class TableNotFoundException extends DomainException {
+
+    public TableNotFoundException(Long id) {
+        super(String.format("Table with id %d doesnt exist",id));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNumberAlreadyExistsException.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNumberAlreadyExistsException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNumberAlreadyExistsException.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.entity.exceptions;
+
+public class TableNumberAlreadyExistsException extends DomainException {
+
+    public TableNumberAlreadyExistsException(Long number) {
+        super(String.format("Table: %d already exists", number));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/AssignmentRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/AssignmentRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/AssignmentRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,14 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Assignment;
+import finki.db.tasty_tabs.web.dto.AssignmentDto;
+import finki.db.tasty_tabs.web.dto.ShiftDto;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface AssignmentRepository extends JpaRepository<Assignment, Long> {
+    Optional<Assignment> findByEmployeeIdAndShiftId(Long employeeId, Long shiftId);
+
+    Optional<Assignment> findFirstByEmployee_IdOrderByShiftStartAsc(Long employeeId);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/BackStaffRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/BackStaffRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/BackStaffRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,7 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.BackStaff;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface BackStaffRepository extends JpaRepository<BackStaff, Long> {
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/CategoryRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/CategoryRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/CategoryRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,44 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Category;
+import jakarta.transaction.Transactional;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface CategoryRepository extends JpaRepository<Category, Long> {
+
+    Optional<Category> findByName(String name);
+    @Query(value = "SELECT * FROM category WHERE id = :id", nativeQuery = true)
+    Category customFindCategoryById(@Param("id") Long id);
+
+    @Query(value = "SELECT * FROM category", nativeQuery = true)
+    List<Category> customFindAllCategories();
+
+    // Custom INSERT (note: JPA doesn't usually do INSERT via query, so avoid this if possible)
+    @Modifying
+    @Transactional
+    @Query(value = "INSERT INTO category (name, is_available) VALUES (:name, :isAvailable)", nativeQuery = true)
+    void customInsertCategory(@Param("name") String name, @Param("isAvailable") Boolean isAvailable);
+
+    @Modifying
+    @Transactional
+    @Query(value = "UPDATE category SET name = :name, is_available = :isAvailable WHERE id = :id", nativeQuery = true)
+    int customUpdateCategory(@Param("id") Long id,
+                       @Param("name") String name,
+                       @Param("isAvailable") Boolean isAvailable);
+
+    @Modifying
+    @Transactional
+    @Query(value = "DELETE FROM category WHERE id = :id", nativeQuery = true)
+    int customDeleteCategoryById(@Param("id") Long id);
+
+    @Query(value = "SELECT * FROM category WHERE name = :name", nativeQuery = true)
+    Category customFindCategoryByName(@Param("name") String name);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/CustomerRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/CustomerRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/CustomerRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,6 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Customer;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface CustomerRepository extends JpaRepository<Customer, Long> {}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/EmployeeRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/EmployeeRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/EmployeeRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,6 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Employee;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface EmployeeRepository extends JpaRepository<Employee, Long> {}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/FrontStaffRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/FrontStaffRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/FrontStaffRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,6 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.FrontStaff;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface FrontStaffRepository extends JpaRepository<FrontStaff, Long> {}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/InventoryRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/InventoryRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/InventoryRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Inventory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface InventoryRepository extends JpaRepository<Inventory,Long> {
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/ManagerRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/ManagerRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/ManagerRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,10 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Manager;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface ManagerRepository extends JpaRepository<Manager, Long> {
+    Optional<Manager> findByEmail(String email);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/OnlineOrderRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/OnlineOrderRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/OnlineOrderRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,17 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Customer;
+import finki.db.tasty_tabs.entity.OnlineOrder;
+import finki.db.tasty_tabs.entity.Order;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface OnlineOrderRepository extends JpaRepository<OnlineOrder, Long> {
+
+    List<OnlineOrder> findAllByCustomer_Id(Long id);
+
+    List<OnlineOrder> findAllByStatusIn(Collection<String> statuses);
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/OrderItemRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/OrderItemRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/OrderItemRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Order;
+import finki.db.tasty_tabs.entity.OrderItem;
+import finki.db.tasty_tabs.entity.Product;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {
+    Optional<OrderItem> findByOrderAndProduct(Order order, Product product);
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/OrderRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/OrderRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/OrderRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Order;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface OrderRepository extends JpaRepository<Order, Long> {
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/PaymentRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/PaymentRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/PaymentRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,12 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Payment;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+@Repository
+public interface PaymentRepository extends JpaRepository<Payment, Long> {
+    // Find a payment by its associated order ID
+    Optional<Payment> findByOrderId(Long orderId);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/ProductRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/ProductRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/ProductRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,12 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Product;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ProductRepository extends JpaRepository<Product, Long> {
+    List<Product> findAllByName(String name);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/ReservationManagedFrontStaffRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/ReservationManagedFrontStaffRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/ReservationManagedFrontStaffRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.ReservationManagedFrontStaff;
+import finki.db.tasty_tabs.entity.composite_keys.ReservationManagedFrontStaffId;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ReservationManagedFrontStaffRepository extends JpaRepository<ReservationManagedFrontStaff, ReservationManagedFrontStaffId> { }
Index: backend/src/main/java/finki/db/tasty_tabs/repository/ReservationRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/ReservationRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/ReservationRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,12 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Reservation;
+import finki.db.tasty_tabs.entity.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import java.time.LocalDateTime;
+import java.util.List;
+
+public interface ReservationRepository extends JpaRepository<Reservation, Long> {
+    List<Reservation> findAllByUser(User user);
+    List<Reservation> findAllByDatetimeBetween(LocalDateTime start, LocalDateTime end);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/RestaurantTableRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/RestaurantTableRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/RestaurantTableRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.RestaurantTable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface RestaurantTableRepository extends JpaRepository<RestaurantTable, Long> {
+
+    List<RestaurantTable> findAllBySeatCapacity(Integer seatCapacity);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/ShiftRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/ShiftRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/ShiftRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.Shift;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ShiftRepository extends JpaRepository<Shift, Long> {}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/StaffRoleRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/StaffRoleRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/StaffRoleRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,6 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.StaffRole;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface StaffRoleRepository extends JpaRepository<StaffRole, Long> {} // Added
Index: backend/src/main/java/finki/db/tasty_tabs/repository/TabOrderRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/TabOrderRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/TabOrderRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,17 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.OnlineOrder;
+import finki.db.tasty_tabs.entity.TabOrder;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+
+public interface TabOrderRepository extends JpaRepository<TabOrder, Long> {
+    List<TabOrder> findByRestaurantTable_TableNumberAndTimestampBetween(Integer tableNumber, LocalDateTime startOfDay, LocalDateTime endOfDay);
+    List<TabOrder> findAllByFrontStaffId(Long frontStaffId);
+    List<TabOrder> findAllByStatus(String status);
+
+    List<TabOrder> findAllByStatusIn(Collection<String> statuses);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/repository/UserRepository.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/repository/UserRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/repository/UserRepository.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,12 @@
+package finki.db.tasty_tabs.repository;
+
+import finki.db.tasty_tabs.entity.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface UserRepository extends JpaRepository<User, Long> {
+    Optional<User> findByEmail(String email);
+
+    boolean existsByEmail(String email);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/AssignmentService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/AssignmentService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/AssignmentService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,18 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.Assignment;
+import finki.db.tasty_tabs.web.dto.CreateAssignmentDto;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+public interface AssignmentService {
+    List<Assignment> getAllAssignments();
+    Assignment getAssignmentById(Long id);
+    Assignment createAssignment(CreateAssignmentDto dto, String managerEmail);
+    Assignment updateAssignment(Long id, CreateAssignmentDto dto, String managerEmail);
+    void deleteAssignment(Long id, String managerEmail);
+    // New method for employee to clock in/out
+    Assignment clockInShift(Long assignmentId, String employeeEmail, LocalDateTime clockInTime);
+    Assignment clockOutShift(Long assignmentId, String employeeEmail, LocalDateTime clockOutTime);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/AuthService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/AuthService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/AuthService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,11 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.web.dto.AuthDto;
+import finki.db.tasty_tabs.web.dto.request.RegisterRequest;
+import finki.db.tasty_tabs.web.dto.UserDto;
+
+public interface AuthService {
+    AuthDto authenticate(String username, String password);
+    AuthDto register(RegisterRequest request);
+    UserDto getAuthenticatedUser();
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/CategoryService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/CategoryService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/CategoryService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,15 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.Category;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface CategoryService {
+    Category findById(Long id);
+    List<Category> getAllCategories();
+    Category updateCategory(Long id,Category category);
+    void deleteCategory(Long id);
+    Category getCategoryByName(String name);
+    Category createCategory(Category category);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/EmployeeService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/EmployeeService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/EmployeeService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,15 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.Employee;
+import finki.db.tasty_tabs.web.dto.AssignmentDto;
+import finki.db.tasty_tabs.web.dto.CreateEmployeeRequest;
+import finki.db.tasty_tabs.web.dto.EmployeeDto;
+
+import java.util.List;
+
+public interface EmployeeService { // New Service
+    List<EmployeeDto> getAllEmployees();
+    Employee createEmployee(CreateEmployeeRequest request);
+
+    AssignmentDto getNextShiftForEmployee(Long employeeId);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/OrderService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/OrderService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/OrderService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,46 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.*;
+import finki.db.tasty_tabs.web.dto.CreateOrderDto;
+import finki.db.tasty_tabs.web.dto.CreateOrderItemDto;
+
+import java.time.LocalDate;
+import java.util.List;
+
+public interface OrderService {
+    List<Order> findAll();
+    Order findById(Long id);
+
+    Order updateOrder(Long id, CreateOrderDto dto);
+    void deleteOrder(Long id);
+
+    double calculateTotalPrice(Long orderId);
+    void updateOrderStatus(Long orderId, String newStatus);
+
+    // Methods for Order Items
+    OrderItem addItemToOrder(Long orderId, CreateOrderItemDto itemDto);
+    void decreaseOrderItemQuantity(Long orderItemId);
+    OrderItem updateOrderItem(Long orderItemId, CreateOrderItemDto itemDto);
+    void deleteOrderItem(Long orderItemId);
+    OrderItem processOrderItem(Long orderItemId);
+
+    // Specific OnlineOrder methods
+    OnlineOrder createOnlineOrder(CreateOrderDto dto, String userEmail);
+    OnlineOrder findOnlineOrderById(Long id);
+    List<OnlineOrder> findAllOnlineOrders();
+    List<OnlineOrder> findOnlineOrdersByCustomer(Long customerId);
+
+    // Specific TabOrder methods
+    TabOrder createTabOrder(CreateOrderDto dto, String userEmail);
+    TabOrder findTabOrderById(Long id);
+    List<TabOrder> findAllTabOrders();
+    List<TabOrder> findTabOrdersByTableAndDate(Integer tableNumber, LocalDate date);
+    List<TabOrder> findTabOrdersByStaff(Long frontStaffId);
+    TabOrder assignOrderToStaff(Long orderId, Long frontStaffId);
+
+    List<Order> findOpenOrders();
+    List<Order> findClosedOrders();
+
+    // General methods for all order types
+    Order cancelOrder(Long orderId);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/PaymentService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/PaymentService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/PaymentService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,14 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.Payment;
+import finki.db.tasty_tabs.web.dto.CreatePaymentDto;
+
+import java.util.List;
+
+public interface PaymentService {
+    Payment createPayment(CreatePaymentDto dto);
+    Payment findPaymentById(Long id);
+    Payment findPaymentByOrderId(Long orderId);
+    List<Payment> findAllPayments();
+    Payment updatePayment(Long id, CreatePaymentDto dto);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/ProductService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/ProductService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/ProductService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,15 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.Product;
+import finki.db.tasty_tabs.web.dto.CreateProductDto;
+
+import java.util.List;
+
+public interface ProductService {
+    Product findById(Long id);
+    List<Product> getAllProducts();
+    Product updateProduct(Long id, CreateProductDto dto);
+    void deleteProduct(Long id);
+    List<Product> getProductsByName(String name);
+    Product createProduct(CreateProductDto dto);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/ReservationService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/ReservationService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/ReservationService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,21 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.Reservation;
+import finki.db.tasty_tabs.entity.ReservationManagedFrontStaff;
+import finki.db.tasty_tabs.web.dto.CreateReservationDto;
+
+import java.time.LocalDate;
+import java.util.List;
+
+public interface ReservationService {
+    List<Reservation> getAllReservations();
+    Reservation getReservationById(Long id);
+    Reservation createReservation(CreateReservationDto dto,String userEmail);
+    Reservation updateReservation(Long id, CreateReservationDto dto,String userEmail);
+    void deleteReservation(Long id);
+    List<Reservation> getAllReservationsByUser(String userEmail);
+    ReservationManagedFrontStaff acceptReservation(Long reservationId, String frontStaffEmail, Long tableNumber);
+
+    List<Reservation> getAllReservationsForToday();
+    List<Reservation> getAllReservationsForDate(LocalDate date);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/RestaurantTableService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/RestaurantTableService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/RestaurantTableService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,15 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.RestaurantTable;
+
+import java.util.List;
+
+public interface RestaurantTableService {
+
+    RestaurantTable findById(Long id);
+    List<RestaurantTable> getAll();
+    RestaurantTable updateTable(Long id, RestaurantTable restaurantTable);
+    void deleteTable(Long id);
+    List<RestaurantTable> getAllBySeatCapacity(Integer seatCapacity);
+    RestaurantTable createTable(RestaurantTable restaurantTable);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/ShiftService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/ShiftService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/ShiftService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,15 @@
+package finki.db.tasty_tabs.service;
+
+import finki.db.tasty_tabs.entity.Shift;
+import finki.db.tasty_tabs.web.dto.CreateShiftDto;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.List;
+
+public interface ShiftService {
+    List<Shift> getAllShifts();
+    Shift getShiftById(Long id);
+    Shift createShift(CreateShiftDto dto, String username);
+    Shift updateShift(Long id, CreateShiftDto dto, String username);
+    void deleteShift(Long id, String username);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/AssignmentServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/AssignmentServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/AssignmentServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,130 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.Assignment;
+import finki.db.tasty_tabs.entity.Employee;
+import finki.db.tasty_tabs.entity.Manager;
+import finki.db.tasty_tabs.entity.Shift;
+import finki.db.tasty_tabs.entity.exceptions.AssignmentNotFoundException;
+import finki.db.tasty_tabs.entity.exceptions.EmployeeNotFoundException;
+import finki.db.tasty_tabs.entity.exceptions.ShiftNotFoundException;
+import finki.db.tasty_tabs.repository.AssignmentRepository;
+import finki.db.tasty_tabs.repository.EmployeeRepository;
+import finki.db.tasty_tabs.repository.ManagerRepository;
+import finki.db.tasty_tabs.repository.ShiftRepository;
+import finki.db.tasty_tabs.service.AssignmentService;
+import finki.db.tasty_tabs.web.dto.CreateAssignmentDto;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Service
+public class AssignmentServiceImpl implements AssignmentService {
+
+    private final AssignmentRepository assignmentRepository;
+    private final ManagerRepository managerRepository;
+    private final EmployeeRepository employeeRepository;
+    private final ShiftRepository shiftRepository;
+
+    public AssignmentServiceImpl(AssignmentRepository assignmentRepository, ManagerRepository managerRepository, EmployeeRepository employeeRepository, ShiftRepository shiftRepository) {
+        this.assignmentRepository = assignmentRepository;
+        this.managerRepository = managerRepository;
+        this.employeeRepository = employeeRepository;
+        this.shiftRepository = shiftRepository;
+    }
+
+    private Manager getManagerByEmail(String email) {
+        return managerRepository.findByEmail(email)
+                .orElseThrow(() -> new AccessDeniedException("Only managers can assign assignments."));
+    }
+
+    @Override
+    public List<Assignment> getAllAssignments() {
+        return assignmentRepository.findAll();
+    }
+
+    @Override
+    public Assignment getAssignmentById(Long id) {
+        return assignmentRepository.findById(id)
+                .orElseThrow(() -> new AssignmentNotFoundException(id));
+    }
+
+    @Override
+    public Assignment createAssignment(CreateAssignmentDto dto, String managerEmail) {
+        Manager manager = getManagerByEmail(managerEmail);
+        Employee employee = employeeRepository.findById(dto.employeeId())
+                .orElseThrow(() -> new EmployeeNotFoundException(dto.employeeId()));
+        Shift shift = shiftRepository.findById(dto.shiftId())
+                .orElseThrow(() -> new ShiftNotFoundException(dto.shiftId()));
+
+        Assignment assignment = new Assignment(
+                dto.clockInTime(),
+                dto.clockOutTime(),
+                manager,
+                employee,
+                shift
+        );
+
+        return assignmentRepository.save(assignment);
+    }
+
+    @Override
+    public Assignment updateAssignment(Long id, CreateAssignmentDto dto, String managerEmail) {
+        Manager manager = getManagerByEmail(managerEmail);
+        Assignment assignment = getAssignmentById(id);
+
+        Employee employee = employeeRepository.findById(dto.employeeId())
+                .orElseThrow(() -> new EmployeeNotFoundException(dto.employeeId()));
+        Shift shift = shiftRepository.findById(dto.shiftId())
+                .orElseThrow(() -> new ShiftNotFoundException(dto.shiftId()));
+
+        assignment.setClockInTime(dto.clockInTime());
+        assignment.setClockOutTime(dto.clockOutTime());
+        assignment.setManager(manager);
+        assignment.setEmployee(employee);
+        assignment.setShift(shift);
+
+        return assignmentRepository.save(assignment);
+    }
+
+    @Override
+    public void deleteAssignment(Long id, String managerEmail) {
+        getManagerByEmail(managerEmail);
+        if (!assignmentRepository.existsById(id)) {
+            throw new AssignmentNotFoundException(id);
+        }
+        assignmentRepository.deleteById(id);
+    }
+    @Override
+    public Assignment clockInShift(Long assignmentId, String employeeEmail, LocalDateTime clockInTime) {
+        Assignment assignment = assignmentRepository.findById(assignmentId)
+                .orElseThrow(() -> new AssignmentNotFoundException( assignmentId));
+
+        // Check if the logged-in employee is assigned to this assignment
+        if (!assignment.getEmployee().getEmail().equals(employeeEmail)) {
+            throw new AccessDeniedException("You can only clock in your own shift.");
+        }
+
+        assignment.setClockInTime(clockInTime);
+        return assignmentRepository.save(assignment);
+    }
+
+    @Override
+    public Assignment clockOutShift(Long assignmentId, String employeeEmail, LocalDateTime clockOutTime) {
+        Assignment assignment = assignmentRepository.findById(assignmentId)
+                .orElseThrow(() -> new AssignmentNotFoundException(assignmentId));
+
+        if (!assignment.getEmployee().getEmail().equals(employeeEmail)) {
+            throw new AccessDeniedException("You can only clock out your own shift.");
+        }
+
+        if (assignment.getClockInTime() == null) {
+            throw new IllegalStateException("Cannot clock out without clocking in first.");
+        }
+
+        assignment.setClockOutTime(clockOutTime);
+        return assignmentRepository.save(assignment);
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/AuthServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/AuthServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/AuthServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,77 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.Customer;
+import finki.db.tasty_tabs.entity.User;
+import finki.db.tasty_tabs.repository.UserRepository;
+import finki.db.tasty_tabs.service.AuthService;
+import finki.db.tasty_tabs.utils.JwtProvider;
+import finki.db.tasty_tabs.web.dto.AuthDto;
+import finki.db.tasty_tabs.web.dto.request.RegisterRequest;
+import finki.db.tasty_tabs.web.dto.UserDto;
+import jakarta.transaction.Transactional;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AuthServiceImpl implements AuthService {
+    private final UserRepository userRepository;
+    private final JwtProvider jwtProvider;
+    private final AuthenticationManager authenticationManager;
+    private final PasswordEncoder passwordEncoder;
+
+    public AuthServiceImpl(UserRepository userRepository, JwtProvider jwtProvider, AuthenticationManager authenticationManager, PasswordEncoder passwordEncoder) {
+        this.userRepository = userRepository;
+        this.jwtProvider = jwtProvider;
+        this.authenticationManager = authenticationManager;
+        this.passwordEncoder = passwordEncoder;
+    }
+
+    @Override
+    public AuthDto authenticate(String email, String password) {
+        Authentication authentication = authenticationManager.authenticate(
+                new UsernamePasswordAuthenticationToken(email, password)
+        );
+
+        User user = userRepository.findByEmail(email)
+                .orElseThrow(() -> new RuntimeException("User not found"));
+
+        String token = jwtProvider.generateToken(user.getEmail());
+
+        return new AuthDto(
+                token,
+                UserDto.from(user)
+        );
+    }
+
+
+    @Override
+    @Transactional
+    public AuthDto register(RegisterRequest request) {
+        User user = userRepository.findByEmail(request.getEmail()).orElse(null);
+        if (user != null){
+            throw new RuntimeException("User with this email already exists");
+        }
+
+        User newUser = new Customer();
+        newUser.setEmail(request.getEmail());
+        newUser.setPassword(passwordEncoder.encode(request.getPassword()));
+        userRepository.save(newUser);
+
+        String token = jwtProvider.generateToken(request.getEmail());
+
+        return new AuthDto(token, UserDto.from(newUser));
+    }
+
+    @Override
+    public UserDto getAuthenticatedUser() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+        return UserDto.from(userRepository.findByEmail(authentication.getName())
+                .orElseThrow(() -> new RuntimeException("User not found")));
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/CategoryServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/CategoryServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/CategoryServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,58 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.Category;
+import finki.db.tasty_tabs.entity.exceptions.CategoryNotFoundException;
+import finki.db.tasty_tabs.repository.CategoryRepository;
+import finki.db.tasty_tabs.service.CategoryService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class CategoryServiceImpl implements CategoryService {
+
+    private final CategoryRepository categoryRepository;
+
+    public CategoryServiceImpl(CategoryRepository categoryRepository) {
+        this.categoryRepository = categoryRepository;
+    }
+
+    @Override
+    public Category findById(Long id) {
+        return categoryRepository.findById(id).orElseThrow(CategoryNotFoundException::new);
+    }
+
+    @Override
+    public List<Category> getAllCategories() {
+        return categoryRepository.findAll();
+    }
+
+    @Override
+    public Category updateCategory(Long id, Category category) {
+        return categoryRepository.findById(id).map(existingCategory -> {
+            if (category.getName() != null) {
+                existingCategory.setName(category.getName());
+            }
+            if (category.getIsAvailable() != null) {
+                existingCategory.setIsAvailable(category.getIsAvailable());
+            }
+            return categoryRepository.save(existingCategory);
+        }).orElseThrow(CategoryNotFoundException::new);
+    }
+
+    @Override
+    public void deleteCategory(Long id) {
+        categoryRepository.deleteById(id);
+    }
+
+    @Override
+    public Category getCategoryByName(String name) {
+        return categoryRepository.findByName(name).orElseThrow(CategoryNotFoundException::new);
+    }
+
+    @Override
+    public Category createCategory(Category category) {
+        return categoryRepository.save(category);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/EmployeeServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/EmployeeServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/EmployeeServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,112 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.*;
+import finki.db.tasty_tabs.repository.*;
+import finki.db.tasty_tabs.service.EmployeeService;
+import finki.db.tasty_tabs.web.dto.AssignmentDto;
+import finki.db.tasty_tabs.web.dto.CreateEmployeeRequest;
+import finki.db.tasty_tabs.web.dto.EmployeeDto;
+import jakarta.persistence.EntityNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@Transactional
+class EmployeeServiceImpl implements EmployeeService { // New Service Implementation
+
+    private final UserRepository userRepository;
+    private final ManagerRepository managerRepository;
+    private final FrontStaffRepository frontStaffRepository;
+    private final BackStaffRepository backStaffRepository;
+    private final StaffRoleRepository staffRoleRepository;
+    private final PasswordEncoder passwordEncoder;
+    private final EmployeeRepository employeeRepository;
+    private final AssignmentRepository assignmentRepository;
+
+    EmployeeServiceImpl(UserRepository userRepository, ManagerRepository managerRepository, FrontStaffRepository frontStaffRepository, BackStaffRepository backStaffRepository, StaffRoleRepository staffRoleRepository, PasswordEncoder passwordEncoder, EmployeeRepository employeeRepository, AssignmentRepository assignmentRepository) {
+        this.userRepository = userRepository;
+        this.managerRepository = managerRepository;
+        this.frontStaffRepository = frontStaffRepository;
+        this.backStaffRepository = backStaffRepository;
+        this.staffRoleRepository = staffRoleRepository;
+        this.passwordEncoder = passwordEncoder;
+        this.employeeRepository = employeeRepository;
+        this.assignmentRepository = assignmentRepository;
+    }
+
+    @Override
+    public List<EmployeeDto> getAllEmployees() {
+        List<Employee> employees = employeeRepository.findAll();
+
+        return employees.stream()
+                .map(EmployeeDto::from)
+                .toList();
+    }
+
+    @Override
+    public AssignmentDto getNextShiftForEmployee(Long employeeId) {
+        Assignment assignment = assignmentRepository.findFirstByEmployee_IdOrderByShiftStartAsc(employeeId).orElse(null);
+
+        if (assignment == null) {
+            throw new EntityNotFoundException("No upcoming shifts found for employee with id: " + employeeId);
+        }
+
+        return AssignmentDto.fromAssignment(assignment);
+    }
+
+    @Override
+    @Transactional
+    public Employee createEmployee(CreateEmployeeRequest request) {
+        // In a real app, you'd check if email is unique and hash the password
+        if (userRepository.existsByEmail(request.email())) {
+             throw new IllegalArgumentException("Employee with email " + request.email() + " already exists.");
+        }
+
+        Employee employee;
+
+        switch (request.employeeType()) {
+            case MANAGER:
+                Manager manager = new Manager();
+                setCommonEmployeeFields(manager, request);
+
+                employee = manager;
+                break;
+            case FRONT_STAFF:
+                FrontStaff frontStaff = new FrontStaff();
+                setCommonEmployeeFields(frontStaff, request);
+                StaffRole frontStaffRole = staffRoleRepository.findById(request.staffRoleId())
+                        .orElseThrow(() -> new EntityNotFoundException("StaffRole not found with id: " + request.staffRoleId()));
+                frontStaff.setStaffRole(frontStaffRole);
+                frontStaff.setTipPercent(request.tipPercent());
+
+                employee = frontStaff;
+                break;
+            case BACK_STAFF:
+                BackStaff backStaff = new BackStaff();
+                setCommonEmployeeFields(backStaff, request);
+                StaffRole backStaffRole = staffRoleRepository.findById(request.staffRoleId())
+                        .orElseThrow(() -> new EntityNotFoundException("StaffRole not found with id: " + request.staffRoleId()));
+                backStaff.setStaffRole(backStaffRole);
+
+                employee = backStaff;
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid employee type: " + request.email());
+        }
+
+        return userRepository.save(employee);
+    }
+
+    private void setCommonEmployeeFields(Employee employee, CreateEmployeeRequest request) {
+        employee.setEmail(request.email());
+        employee.setPassword(passwordEncoder.encode(request.password()));
+        employee.setStreet(request.street());
+        employee.setCity(request.city());
+        employee.setPhoneNumber(request.phoneNumber());
+        employee.setNetSalary(request.netSalary());
+        employee.setGrossSalary(request.grossSalary());
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/OrderServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/OrderServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/OrderServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,307 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.*;
+import finki.db.tasty_tabs.entity.exceptions.*;
+import finki.db.tasty_tabs.repository.*;
+import finki.db.tasty_tabs.service.OrderService;
+import finki.db.tasty_tabs.web.dto.CreateOrderDto;
+import finki.db.tasty_tabs.web.dto.CreateOrderItemDto;
+import jakarta.transaction.Transactional;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class OrderServiceImpl implements OrderService {
+
+    private final OrderRepository orderRepository;
+    private final OrderItemRepository orderItemRepository;
+    private final ProductRepository productRepository;
+    private final RestaurantTableRepository tableRepository;
+    private final UserRepository userRepository;
+    private final TabOrderRepository tabOrderRepository;
+    private final OnlineOrderRepository onlineOrderRepository;
+    private final FrontStaffRepository frontStaffRepository;
+    private final CustomerRepository customerRepository;
+
+    @Override
+    public List<Order> findAll() {
+        return orderRepository.findAll();
+    }
+
+    @Override
+    public Order findById(Long id) {
+        return orderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException(id));
+    }
+
+    @Override
+    public Order updateOrder(Long id, CreateOrderDto dto) {
+        Order existingOrder = findById(id);
+
+        existingOrder.setStatus(dto.status());
+
+        existingOrder.getOrderItems().clear();
+        List<OrderItem> newOrderItems = dto.orderItems().stream().map(itemDto -> {
+            OrderItem item = new OrderItem();
+            item.setOrder(existingOrder);
+            item.setQuantity(itemDto.quantity());
+            item.setPrice(itemDto.price());
+            item.setIsProcessed(itemDto.isProcessed());
+            item.setTimestamp(LocalDateTime.now());
+            Product product = productRepository.findById(itemDto.productId())
+                    .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
+            item.setProduct(product);
+            return item;
+        }).collect(Collectors.toList());
+
+        existingOrder.setOrderItems(newOrderItems);
+
+        return orderRepository.save(existingOrder);
+    }
+
+    @Override
+    public void deleteOrder(Long id) {
+        orderRepository.deleteById(id);
+    }
+
+    @Override
+    public double calculateTotalPrice(Long orderId) {
+        Order order = findById(orderId);
+        return order.getOrderItems().stream()
+                .mapToDouble(item -> item.getQuantity() * item.getPrice())
+                .sum();
+    }
+
+    @Override
+    public void updateOrderStatus(Long orderId, String newStatus) {
+        Order order = findById(orderId);
+        order.setStatus(newStatus);
+        orderRepository.save(order);
+    }
+
+    // Methods for Order Items
+    @Override
+    @Transactional
+    public OrderItem addItemToOrder(Long orderId, CreateOrderItemDto itemDto) {
+        Order order = findById(orderId);
+        OrderItem orderItem = new OrderItem();
+        orderItem.setOrder(order);
+        orderItem.setQuantity(itemDto.quantity());
+        orderItem.setPrice(itemDto.price());
+        orderItem.setIsProcessed(itemDto.isProcessed());
+        orderItem.setTimestamp(LocalDateTime.now());
+        Product product = productRepository.findById(itemDto.productId())
+                .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
+        orderItem.setProduct(product);
+        return orderItemRepository.save(orderItem);
+    }
+
+    @Override
+    @Transactional
+    public void decreaseOrderItemQuantity(Long orderItemId) {
+        OrderItem orderItem = orderItemRepository.findById(orderItemId)
+                .orElseThrow(OrderItemNotFoundException::new);
+        if (orderItem.getQuantity() > 1) {
+            orderItem.setQuantity(orderItem.getQuantity() - 1);
+            orderItemRepository.save(orderItem);
+        } else {
+            orderItemRepository.delete(orderItem);
+        }
+    }
+
+    @Override
+    @Transactional
+    public OrderItem updateOrderItem(Long orderItemId, CreateOrderItemDto itemDto) {
+        OrderItem orderItem = orderItemRepository.findById(orderItemId)
+                .orElseThrow(OrderItemNotFoundException::new);
+        orderItem.setQuantity(itemDto.quantity());
+        orderItem.setPrice(itemDto.price());
+        orderItem.setIsProcessed(itemDto.isProcessed());
+        Product product = productRepository.findById(itemDto.productId())
+                .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
+        orderItem.setProduct(product);
+        return orderItemRepository.save(orderItem);
+    }
+
+    @Override
+    @Transactional
+    public void deleteOrderItem(Long orderItemId) {
+        orderItemRepository.deleteById(orderItemId);
+    }
+
+    @Override
+    @Transactional
+    public OrderItem processOrderItem(Long orderItemId) {
+        OrderItem orderItem = orderItemRepository.findById(orderItemId)
+                .orElseThrow(OrderItemNotFoundException::new);
+        orderItem.setIsProcessed(true);
+        return orderItemRepository.save(orderItem);
+    }
+
+    // Specific OnlineOrder methods
+    @Override
+    @Transactional
+    public OnlineOrder createOnlineOrder(CreateOrderDto dto, String userEmail) {
+        User user = userRepository.findByEmail(userEmail)
+                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
+        if (!(user instanceof Customer)) {
+            throw new SecurityException("User is not authorized to create online orders.");
+        }
+        OnlineOrder onlineOrder = new OnlineOrder();
+        onlineOrder.setCustomer((Customer) user);
+        onlineOrder.setDeliveryAddress(dto.deliveryAddress());
+        onlineOrder.setTimestamp(LocalDateTime.now());
+        onlineOrder.setStatus(dto.status());
+        if (dto.orderItems() != null && !dto.orderItems().isEmpty()) {
+            List<OrderItem> orderItems = dto.orderItems().stream().map(itemDto -> {
+                OrderItem item = new OrderItem();
+                item.setOrder(onlineOrder);
+                item.setQuantity(itemDto.quantity());
+                item.setPrice(itemDto.price());
+                item.setIsProcessed(itemDto.isProcessed());
+                item.setTimestamp(LocalDateTime.now());
+                Product product = productRepository.findById(itemDto.productId())
+                        .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
+                item.setProduct(product);
+                return item;
+            }).collect(Collectors.toList());
+            onlineOrder.setOrderItems(orderItems);
+        }
+        return onlineOrderRepository.save(onlineOrder);
+    }
+
+    @Override
+    public OnlineOrder findOnlineOrderById(Long id) {
+        return onlineOrderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException(id));
+    }
+
+    @Override
+    public List<OnlineOrder> findAllOnlineOrders() {
+        return onlineOrderRepository.findAll();
+    }
+
+    @Override
+    public List<OnlineOrder> findOnlineOrdersByCustomer(Long customerId) {
+        return onlineOrderRepository.findAllByCustomer_Id(customerId);
+    }
+
+    // Specific TabOrder methods
+    @Override
+    @Transactional
+    public TabOrder createTabOrder(CreateOrderDto dto, String userEmail) {
+        log.debug("User {} creating a tab order for table {}", userEmail, dto.tableNumber());
+        User user = userRepository.findByEmail(userEmail)
+                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
+        if (!(user instanceof FrontStaff)) {
+            throw new SecurityException("User is not authorized to create tab orders.");
+        }
+        TabOrder tabOrder = new TabOrder();
+        RestaurantTable table = tableRepository.findById(dto.tableNumber())
+                .orElseThrow(() -> new TableNotFoundException(dto.tableNumber()));
+        tabOrder.setRestaurantTable(table);
+        tabOrder.setFrontStaff((FrontStaff) user);
+        tabOrder.setTimestamp(LocalDateTime.now());
+        tabOrder.setStatus(dto.status());
+        if (dto.orderItems() != null && !dto.orderItems().isEmpty()) {
+            log.debug("OrderItems is not empty, processing items...");
+            List<OrderItem> orderItems = dto.orderItems().stream().map(itemDto -> {
+                OrderItem item = new OrderItem();
+                item.setOrder(tabOrder);
+                item.setQuantity(itemDto.quantity());
+                item.setPrice(itemDto.price());
+                item.setIsProcessed(itemDto.isProcessed());
+                item.setTimestamp(LocalDateTime.now());
+                Product product = productRepository.findById(itemDto.productId())
+                        .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
+                item.setProduct(product);
+                return item;
+            }).collect(Collectors.toList());
+            tabOrder.setOrderItems(orderItems);
+        }
+        return tabOrderRepository.save(tabOrder);
+    }
+
+    @Override
+    public TabOrder findTabOrderById(Long id) {
+        return tabOrderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException(id));
+    }
+
+    @Override
+    public List<TabOrder> findAllTabOrders() {
+        return tabOrderRepository.findAll();
+    }
+
+    @Override
+    public List<TabOrder> findTabOrdersByTableAndDate(Integer tableNumber, LocalDate date) {
+        LocalDateTime startOfDay = date.atStartOfDay();
+        LocalDateTime endOfDay = date.atTime(23, 59, 59);
+        return tabOrderRepository.findByRestaurantTable_TableNumberAndTimestampBetween(tableNumber, startOfDay, endOfDay);
+    }
+
+    @Override
+    public List<TabOrder> findTabOrdersByStaff(Long frontStaffId) {
+        return tabOrderRepository.findAllByFrontStaffId(frontStaffId);
+    }
+
+    @Override
+    @Transactional
+    public TabOrder assignOrderToStaff(Long orderId, Long frontStaffId) {
+        TabOrder tabOrder = tabOrderRepository.findById(orderId)
+                .orElseThrow(() -> new OrderNotFoundException(orderId));
+        FrontStaff frontStaff = frontStaffRepository.findById(frontStaffId)
+                .orElseThrow(() -> new FrontStaffNotFoundException(frontStaffId));
+        tabOrder.setFrontStaff(frontStaff);
+        return tabOrderRepository.save(tabOrder);
+    }
+
+    // General methods for all order types
+    @Override
+    @Transactional
+    public Order cancelOrder(Long orderId) {
+        Order order = findById(orderId);
+        order.setStatus("CANCELED");
+        return orderRepository.save(order);
+    }
+
+    @Override
+    public List<Order> findOpenOrders() {
+
+        // Query the OnlineOrderRepository for open orders
+        List<OnlineOrder> onlineOrders = onlineOrderRepository.findAllByStatusIn(List.of("PENDING", "CONFIRMED"));
+
+        // Query the TabOrderRepository for open orders
+        List<TabOrder> tabOrders = tabOrderRepository.findAllByStatusIn(List.of("PENDING", "CONFIRMED"));
+
+        // Combine the lists into a single List<Order>
+        List<Order> combinedOrders = new java.util.ArrayList<>();
+        combinedOrders.addAll(onlineOrders);
+        combinedOrders.addAll(tabOrders);
+
+        return combinedOrders;
+    }
+
+    @Override
+    public List<Order> findClosedOrders() {
+
+        // Query the OnlineOrderRepository for open orders
+        List<OnlineOrder> onlineOrders = onlineOrderRepository.findAllByStatusIn(List.of("CLOSED"));
+
+        // Query the TabOrderRepository for open orders
+        List<TabOrder> tabOrders = tabOrderRepository.findAllByStatus("CLOSED");
+
+        // Combine the lists into a single List<Order>
+        List<Order> combinedOrders = new java.util.ArrayList<>();
+        combinedOrders.addAll(onlineOrders);
+        combinedOrders.addAll(tabOrders);
+
+        return combinedOrders;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/PaymentServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/PaymentServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/PaymentServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,71 @@
+package finki.db.tasty_tabs.service.impl;
+
+
+import finki.db.tasty_tabs.entity.Order;
+import finki.db.tasty_tabs.entity.Payment;
+import finki.db.tasty_tabs.entity.exceptions.OrderNotFoundException;
+import finki.db.tasty_tabs.entity.exceptions.PaymentNotFoundException;
+import finki.db.tasty_tabs.repository.OrderRepository;
+import finki.db.tasty_tabs.repository.PaymentRepository;
+import finki.db.tasty_tabs.service.PaymentService;
+import finki.db.tasty_tabs.web.dto.CreatePaymentDto;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import jakarta.transaction.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class PaymentServiceImpl implements PaymentService {
+
+    private final PaymentRepository paymentRepository;
+    private final OrderRepository orderRepository;
+
+    @Override
+    @Transactional
+    public Payment createPayment(CreatePaymentDto dto) {
+        Order order = orderRepository.findById(dto.orderId())
+                .orElseThrow(() -> new OrderNotFoundException(dto.orderId()));
+
+        Payment payment = new Payment();
+        payment.setAmount(dto.amount());
+        payment.setTipAmount(dto.tipAmount());
+        payment.setPaymentType(dto.paymentType());
+        payment.setTimestamp(LocalDateTime.now());
+        payment.setOrder(order);
+
+        return paymentRepository.save(payment);
+    }
+
+    @Override
+    public Payment findPaymentById(Long id) {
+        return paymentRepository.findById(id)
+                .orElseThrow(() -> new PaymentNotFoundException(id));
+    }
+
+    @Override
+    public Payment findPaymentByOrderId(Long orderId) {
+        return paymentRepository.findByOrderId(orderId)
+                .orElseThrow(() -> new PaymentNotFoundException(orderId));
+    }
+
+    @Override
+    public List<Payment> findAllPayments() {
+        return paymentRepository.findAll();
+    }
+
+    @Override
+    @Transactional
+    public Payment updatePayment(Long id, CreatePaymentDto dto) {
+        Payment existingPayment = findPaymentById(id);
+
+        existingPayment.setAmount(dto.amount());
+        existingPayment.setTipAmount(dto.tipAmount());
+        existingPayment.setPaymentType(dto.paymentType());
+
+        return paymentRepository.save(existingPayment);
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/ProductServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/ProductServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/ProductServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,131 @@
+package finki.db.tasty_tabs.service.impl;
+
+
+import finki.db.tasty_tabs.entity.Inventory;
+import finki.db.tasty_tabs.entity.Product;
+import finki.db.tasty_tabs.entity.exceptions.ProductNotFoundException;
+import finki.db.tasty_tabs.repository.InventoryRepository;
+import finki.db.tasty_tabs.repository.ProductRepository;
+import finki.db.tasty_tabs.service.CategoryService;
+import finki.db.tasty_tabs.service.ProductService;
+import finki.db.tasty_tabs.web.dto.CreateProductDto;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class ProductServiceImpl implements ProductService {
+
+    private final ProductRepository productRepository;
+    private final CategoryService categoryService;
+    private final InventoryRepository inventoryRepository;
+
+
+    public ProductServiceImpl(ProductRepository productRepository, CategoryService categoryService,InventoryRepository inventoryRepository) {
+        this.productRepository = productRepository;
+        this.categoryService = categoryService;
+        this.inventoryRepository=inventoryRepository;
+    }
+
+    @Override
+    public Product findById(Long id) {
+        return productRepository.findById(id)
+                .orElseThrow(() -> new ProductNotFoundException(id));
+    }
+
+    @Override
+    public List<Product> getAllProducts() {
+        return productRepository.findAll();
+    }
+
+    @Override
+    public Product updateProduct(Long id, CreateProductDto dto) {
+        Product existingProduct = productRepository.findById(id)
+                .orElseThrow(() -> new ProductNotFoundException(id));
+
+        // Update product fields
+        if (dto.name() != null) {
+            existingProduct.setName(dto.name());
+        }
+        if (dto.price() != null) {
+            existingProduct.setPrice(dto.price());
+        }
+        if (dto.taxClass() != null) {
+            existingProduct.setTaxClass(dto.taxClass());
+        }
+        if (dto.categoryId() != null) {
+            existingProduct.setCategory(categoryService.findById(dto.categoryId()));
+        }
+        if (dto.description() != null) {
+            existingProduct.setDescription(dto.description());
+        }
+
+        // Manage inventory
+        if (Boolean.TRUE.equals(dto.manageInventory())) {
+            // ако производот претходно не менаџирал inventory -> креирај нов
+            if (Boolean.FALSE.equals(existingProduct.getManageInventory())) {
+                Inventory inventory = new Inventory(existingProduct, dto.quantity(), dto.restockLevel());
+                inventoryRepository.save(inventory);
+            } else {
+                // ако веќе постои -> update
+                Inventory inventory = inventoryRepository.findById(id)
+                        .orElseThrow(() -> new RuntimeException("Inventory not found for product " + id));
+                if (dto.quantity() != null) {
+                    inventory.setQuantity(dto.quantity());
+                }
+                if (dto.restockLevel() != null) {
+                    inventory.setRestockLevel(dto.restockLevel());
+                }
+                inventoryRepository.save(inventory);
+            }
+        } else if (Boolean.FALSE.equals(dto.manageInventory())) {
+            // ако од TRUE се префрла на FALSE -> бриши го inventory-то
+            inventoryRepository.findById(id).ifPresent(inventoryRepository::delete);
+        }
+
+        // на крај секогаш го сетирај manageInventory флагот
+        if (dto.manageInventory() != null) {
+            existingProduct.setManageInventory(dto.manageInventory());
+        }
+
+        return productRepository.save(existingProduct);
+    }
+
+    @Override
+    public void deleteProduct(Long id) {
+        productRepository.deleteById(id);
+    }
+
+    @Override
+    public List<Product> getProductsByName(String name) {
+
+        return productRepository.findAllByName(name);
+    }
+
+    @Override
+    public Product createProduct(CreateProductDto dto) {
+        Product productTmp=new Product();
+        if (dto.name() != null) {
+            productTmp.setName(dto.name());
+        }
+        if (dto.price() != null) {
+            productTmp.setPrice(dto.price());
+        }
+        if(dto.taxClass()!=null){
+            productTmp.setTaxClass(dto.taxClass());
+        }
+        productTmp.setCategory(categoryService.findById(dto.categoryId()));
+        productTmp.setDescription(dto.description());
+
+        if(dto.manageInventory()!=null){
+            productTmp.setManageInventory(dto.manageInventory());
+        }
+        Product product=productRepository.save(productTmp);
+        if(product.getManageInventory()==Boolean.TRUE){
+            Inventory inventory = new Inventory(product, dto.quantity(), dto.restockLevel());
+            inventoryRepository.save(inventory);
+        }
+        return product;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/ReservationServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/ReservationServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/ReservationServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,141 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.*;
+import finki.db.tasty_tabs.entity.composite_keys.ReservationManagedFrontStaffId;
+import finki.db.tasty_tabs.entity.exceptions.ReservationNotFoundException;
+import finki.db.tasty_tabs.entity.exceptions.TableNotFoundException;
+import finki.db.tasty_tabs.repository.*;
+import finki.db.tasty_tabs.service.ReservationService;
+import finki.db.tasty_tabs.web.dto.CreateReservationDto;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Service
+public class ReservationServiceImpl implements ReservationService {
+
+    private final ReservationRepository reservationRepository;
+    private final UserRepository userRepository;
+    private final FrontStaffRepository frontStaffRepository;
+    private final RestaurantTableRepository restaurantTableRepository;
+    private final ReservationManagedFrontStaffRepository reservationManagedFrontStaffRepository;
+
+    public ReservationServiceImpl(ReservationRepository reservationRepository, UserRepository userRepository, FrontStaffRepository frontStaffRepository, RestaurantTableRepository restaurantTableRepository, ReservationManagedFrontStaffRepository reservationManagedFrontStaffRepository) {
+        this.reservationRepository = reservationRepository;
+        this.userRepository = userRepository;
+        this.frontStaffRepository = frontStaffRepository;
+        this.restaurantTableRepository = restaurantTableRepository;
+        this.reservationManagedFrontStaffRepository = reservationManagedFrontStaffRepository;
+    }
+
+    @Override
+    public List<Reservation> getAllReservations() {
+        return reservationRepository.findAll();
+    }
+
+    @Override
+    public Reservation getReservationById(Long id) {
+        return reservationRepository.findById(id)
+                .orElseThrow(() -> new ReservationNotFoundException(id));
+    }
+
+    @Override
+    public Reservation createReservation(CreateReservationDto dto, String userEmail) {
+        User user = userRepository.findByEmail(userEmail)
+                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
+
+        Reservation reservation = new Reservation();
+        reservation.setStayLength(dto.stayLength());
+        reservation.setDatetime(dto.datetime());
+        reservation.setNumberOfPeople(dto.numberOfPeople());
+        reservation.setUser(user);
+        reservation.setCreationTimestamp(LocalDateTime.now());
+
+        return reservationRepository.save(reservation);
+    }
+
+    @Override
+    public Reservation updateReservation(Long id, CreateReservationDto dto, String userEmail) {
+        Reservation existing = getReservationById(id);
+
+        User user = userRepository.findByEmail(userEmail)
+                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
+
+        // Optionally, add a check if the logged-in user is allowed to update this reservation
+        if (!existing.getUser().getId().equals(user.getId())) {
+            throw new SecurityException("You are not authorized to update this reservation.");
+        }
+
+        existing.setStayLength(dto.stayLength());
+        existing.setDatetime(dto.datetime());
+        existing.setNumberOfPeople(dto.numberOfPeople());
+        existing.setUser(user);
+
+        return reservationRepository.save(existing);
+    }
+
+    @Override
+    public void deleteReservation(Long id) {
+        reservationRepository.deleteById(id);
+    }
+
+    @Override
+    public List<Reservation> getAllReservationsByUser(String userEmail) {
+        User user = userRepository.findByEmail(userEmail)
+                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
+        return reservationRepository.findAllByUser(user);
+    }
+
+    @Override
+    public ReservationManagedFrontStaff acceptReservation(Long reservationId, String frontStaffEmail, Long tableNumber) {
+        User user = userRepository.findByEmail(frontStaffEmail)
+                .orElseThrow(() -> new UsernameNotFoundException("User with email " + frontStaffEmail + " not found."));
+
+        if (!(user instanceof FrontStaff)) {
+            throw new SecurityException("User is not authorized to accept reservations as they are not a FrontStaff member.");
+        }
+        FrontStaff frontStaff = (FrontStaff) user;
+        // 2. Fetch all other required entities
+        Reservation reservation = reservationRepository.findById(reservationId)
+                .orElseThrow(() -> new ReservationNotFoundException(reservationId));
+
+        RestaurantTable table = restaurantTableRepository.findById(tableNumber)
+                .orElseThrow(() -> new TableNotFoundException(tableNumber));
+
+        // 3. Create the new ReservationManagedFrontStaff entity
+        ReservationManagedFrontStaffId id = new ReservationManagedFrontStaffId(
+                reservation.getId(),
+                frontStaff.getId(),
+                table.getTableNumber().longValue()
+        );
+
+        ReservationManagedFrontStaff managedReservation = new ReservationManagedFrontStaff();
+        managedReservation.setReservation(reservation);
+        managedReservation.setFrontStaff(frontStaff);
+        managedReservation.setRestaurantTable(table);
+        managedReservation.setId(id);
+
+        // 4. Save the new entity to the database
+        return reservationManagedFrontStaffRepository.save(managedReservation);
+    }
+    @Override
+    public List<Reservation> getAllReservationsForToday() {
+        LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
+        LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59);
+
+        return reservationRepository.findAllByDatetimeBetween(startOfDay, endOfDay);
+    }
+
+    @Override
+    public List<Reservation> getAllReservationsForDate(LocalDate date) {
+        LocalDateTime startOfDay = date.atStartOfDay();
+        LocalDateTime endOfDay = date.atTime(23, 59, 59);
+
+        return reservationRepository.findAllByDatetimeBetween(startOfDay, endOfDay);
+    }
+
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/RestaurantTableServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/RestaurantTableServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/RestaurantTableServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,65 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.RestaurantTable;
+import finki.db.tasty_tabs.entity.exceptions.TableNotFoundException;
+import finki.db.tasty_tabs.entity.exceptions.TableNumberAlreadyExistsException;
+import finki.db.tasty_tabs.repository.RestaurantTableRepository;
+import finki.db.tasty_tabs.service.RestaurantTableService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class RestaurantTableServiceImpl implements RestaurantTableService {
+
+    private final RestaurantTableRepository tableRepository;
+
+    public RestaurantTableServiceImpl(RestaurantTableRepository tableRepository) {
+        this.tableRepository = tableRepository;
+    }
+
+    @Override
+    public RestaurantTable findById(Long id) {
+        return tableRepository.findById(id).orElseThrow(()->new TableNotFoundException(id));
+    }
+
+    @Override
+    public List<RestaurantTable> getAll() {
+        return tableRepository.findAll();
+    }
+
+    @Override
+    public RestaurantTable updateTable(Long id, RestaurantTable restaurantTable) {
+        if(tableRepository.findById(restaurantTable.getTableNumber()).isPresent() && id!=restaurantTable.getTableNumber()){
+            throw new TableNumberAlreadyExistsException(restaurantTable.getTableNumber());
+        }
+        return tableRepository.findById(id).map(existingTable -> {
+            if (restaurantTable.getTableNumber() != null) {
+                existingTable.setTableNumber(restaurantTable.getTableNumber());
+            }
+            if (restaurantTable.getSeatCapacity() != null) {
+                existingTable.setSeatCapacity(restaurantTable.getSeatCapacity());
+            }
+            return tableRepository.save(existingTable);
+        }).orElseThrow(()->new TableNotFoundException(id));
+    }
+
+    @Override
+    public void deleteTable(Long id) {
+        tableRepository.deleteById(id);
+    }
+
+
+    @Override
+    public List<RestaurantTable> getAllBySeatCapacity(Integer seatCapacity) {
+        return tableRepository.findAllBySeatCapacity(seatCapacity);
+    }
+
+    @Override
+    public RestaurantTable createTable(RestaurantTable restaurantTable) {
+        if(tableRepository.findById(restaurantTable.getTableNumber()).isPresent()){
+            throw new TableNumberAlreadyExistsException(restaurantTable.getTableNumber());
+        }
+        return tableRepository.save(restaurantTable);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/service/impl/ShiftServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/service/impl/ShiftServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/service/impl/ShiftServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,79 @@
+package finki.db.tasty_tabs.service.impl;
+
+import finki.db.tasty_tabs.entity.Assignment;
+import finki.db.tasty_tabs.entity.Employee;
+import finki.db.tasty_tabs.entity.Manager;
+import finki.db.tasty_tabs.entity.Shift;
+import finki.db.tasty_tabs.entity.exceptions.ShiftNotFoundException;
+import finki.db.tasty_tabs.repository.AssignmentRepository;
+import finki.db.tasty_tabs.repository.EmployeeRepository;
+import finki.db.tasty_tabs.repository.ManagerRepository;
+import finki.db.tasty_tabs.repository.ShiftRepository;
+import finki.db.tasty_tabs.service.ShiftService;
+import finki.db.tasty_tabs.web.dto.AssignmentDto;
+import finki.db.tasty_tabs.web.dto.ClockInRequest;
+import finki.db.tasty_tabs.web.dto.CreateShiftDto;
+import finki.db.tasty_tabs.web.dto.ShiftDto;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import jakarta.persistence.EntityNotFoundException;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Service
+public class ShiftServiceImpl implements ShiftService{
+    private final ShiftRepository shiftRepository;
+    private final ManagerRepository managerRepository;
+
+    public ShiftServiceImpl(ShiftRepository shiftRepository, ManagerRepository managerRepository) {
+        this.shiftRepository = shiftRepository;
+        this.managerRepository = managerRepository;
+    }
+
+    private Manager getManagerByUsername(String username) {
+        return managerRepository.findByEmail(username)
+                .orElseThrow(() -> new AccessDeniedException("Only managers can assign shifts."));
+    }
+
+    @Override
+    public List<Shift> getAllShifts() {
+        return shiftRepository.findAll();
+    }
+
+    @Override
+    public Shift getShiftById(Long id) {
+        return shiftRepository.findById(id)
+                .orElseThrow(() -> new ShiftNotFoundException(id));
+    }
+
+    @Override
+    public Shift createShift(CreateShiftDto dto, String username) {
+        Manager manager = getManagerByUsername(username);
+        Shift shift = new Shift(dto.date(), dto.start(), dto.end(), manager);
+        return shiftRepository.save(shift);
+    }
+
+    @Override
+    public Shift updateShift(Long id, CreateShiftDto dto, String username) {
+        Manager manager = getManagerByUsername(username);
+        Shift shift = getShiftById(id);
+
+        shift.setDate(dto.date());
+        shift.setStart(dto.start());
+        shift.setEnd(dto.end());
+        shift.setManager(manager);
+
+        return shiftRepository.save(shift);
+    }
+
+    @Override
+    public void deleteShift(Long id, String username) {
+        getManagerByUsername(username);
+        if (!shiftRepository.existsById(id)) {
+            throw new ShiftNotFoundException(id);
+        }
+        shiftRepository.deleteById(id);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/utils/JwtProvider.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/utils/JwtProvider.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/utils/JwtProvider.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,36 @@
+package finki.db.tasty_tabs.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.security.Keys;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+@Component
+public class JwtProvider {
+    @Value("${jwt.secret}")
+    private String jwtSecret;
+    @Value("${jwt.expiration}")
+    private long jwtExpiration;
+
+    public String generateToken(String email) {
+        return Jwts.builder()
+                .setSubject(String.valueOf(email)) // Use user ID as the subject
+                .setIssuedAt(new Date()) // Token issue time
+                .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration)) // Token expiration
+                .signWith(Keys.hmacShaKeyFor(jwtSecret.getBytes()), SignatureAlgorithm.HS256) // HMAC-SHA256 signing
+                .compact();
+    }
+
+    public Claims validateToken(String token) {
+        return Jwts.parserBuilder()
+                .setSigningKey(jwtSecret.getBytes())
+                .build()
+                .parseClaimsJws(token)
+                .getBody();
+    }
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/AssignmentController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/AssignmentController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/AssignmentController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,110 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.entity.Assignment;
+import finki.db.tasty_tabs.service.AssignmentService;
+import finki.db.tasty_tabs.web.dto.AssignmentDto;
+import finki.db.tasty_tabs.web.dto.CreateAssignmentDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/assignments")
+@Tag(name = "Assignment API", description = "Endpoints for managing shift assignments (Manager only)")
+public class AssignmentController {
+
+    private final AssignmentService assignmentService;
+
+    public AssignmentController(AssignmentService assignmentService) {
+        this.assignmentService = assignmentService;
+    }
+
+    @Operation(summary = "Get all assignments")
+    @GetMapping
+    public List<AssignmentDto> getAllAssignments() {
+        return assignmentService.getAllAssignments()
+                .stream()
+                .map(AssignmentDto::fromAssignment)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get assignment by ID")
+    @GetMapping("/{id}")
+    public ResponseEntity<AssignmentDto> getAssignmentById(@PathVariable Long id) {
+        return ResponseEntity.ok(AssignmentDto.fromAssignment(assignmentService.getAssignmentById(id)));
+    }
+
+    @Operation(summary = "Create assignment (Manager only)")
+    @PostMapping
+    public ResponseEntity<AssignmentDto> createAssignment(@RequestBody CreateAssignmentDto dto, Authentication authentication) {
+        try {
+            String managerEmail = authentication.getName();
+            Assignment assignment = assignmentService.createAssignment(dto, managerEmail);
+            return ResponseEntity.status(HttpStatus.CREATED).body(AssignmentDto.fromAssignment(assignment));
+        } catch (SecurityException e) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
+        }
+    }
+
+    @Operation(summary = "Update assignment (Manager only)")
+    @PutMapping("/{id}")
+    public ResponseEntity<AssignmentDto> updateAssignment(@PathVariable Long id, @RequestBody CreateAssignmentDto dto, Authentication authentication) {
+        try {
+            String managerEmail = authentication.getName();
+            Assignment updated = assignmentService.updateAssignment(id, dto, managerEmail);
+            return ResponseEntity.ok(AssignmentDto.fromAssignment(updated));
+        } catch (SecurityException e) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
+        }
+    }
+
+    @Operation(summary = "Delete assignment (Manager only)")
+    @DeleteMapping("/{id}")
+    public ResponseEntity<Void> deleteAssignment(@PathVariable Long id, Authentication authentication) {
+        try {
+            String managerEmail = authentication.getName();
+            assignmentService.deleteAssignment(id, managerEmail);
+            return ResponseEntity.noContent().build();
+        } catch (SecurityException e) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
+        }
+    }
+
+    @Operation(summary = "Employee clocks in their shift")
+    @PostMapping("/{id}/clockin")
+    public ResponseEntity<AssignmentDto> clockInShift(
+            @PathVariable Long id,
+            @RequestParam(required = false) LocalDateTime clockInTime,
+            Authentication authentication) {
+        try {
+            String employeeEmail = authentication.getName();
+            LocalDateTime timeToSet = clockInTime != null ? clockInTime : LocalDateTime.now();
+            Assignment assignment = assignmentService.clockInShift(id, employeeEmail, timeToSet);
+            return ResponseEntity.ok(AssignmentDto.fromAssignment(assignment));
+        } catch (SecurityException e) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
+        }
+    }
+
+    @Operation(summary = "Employee clocks out their shift")
+    @PostMapping("/{id}/clockout")
+    public ResponseEntity<AssignmentDto> clockOutShift(
+            @PathVariable Long id,
+            @RequestParam(required = false) LocalDateTime clockOutTime,
+            Authentication authentication) {
+        try {
+            String employeeEmail = authentication.getName();
+            LocalDateTime timeToSet = clockOutTime != null ? clockOutTime : LocalDateTime.now();
+            Assignment assignment = assignmentService.clockOutShift(id, employeeEmail, timeToSet);
+            return ResponseEntity.ok(AssignmentDto.fromAssignment(assignment));
+        } catch (SecurityException e) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
+        }
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/AuthController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/AuthController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/AuthController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,32 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.service.AuthService;
+import finki.db.tasty_tabs.web.dto.AuthDto;
+import finki.db.tasty_tabs.web.dto.request.RegisterRequest;
+import finki.db.tasty_tabs.web.dto.request.AuthRequest;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/auth")
+@Tag(name = "Auth", description = "Authentication and authorization endpoints")
+@RequiredArgsConstructor
+public class AuthController {
+    private final AuthService authService;
+
+    @PostMapping("/login")
+    public ResponseEntity<AuthDto> authenticate(@Valid @RequestBody AuthRequest authDto) {
+        return ResponseEntity.ok(authService.authenticate(authDto.username(), authDto.password()));
+    }
+
+    @PostMapping("/register")
+    public ResponseEntity<AuthDto> register(@Valid @RequestBody RegisterRequest registerRequest) {
+        return ResponseEntity.ok(authService.register(registerRequest));
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/CategoryController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/CategoryController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/CategoryController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,63 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.entity.Category;
+import finki.db.tasty_tabs.service.CategoryService;
+import finki.db.tasty_tabs.web.dto.CategoryDto;
+import finki.db.tasty_tabs.web.dto.CreateCategoryDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/categories")
+@Tag(name = "Category API", description = "Endpoints for managing product categories")
+public class CategoryController {
+
+    private final CategoryService categoryService;
+
+    public CategoryController(CategoryService categoryService) {
+        this.categoryService = categoryService;
+    }
+
+    @Operation(summary = "Get all categories")
+    @GetMapping
+    public ResponseEntity<List<CategoryDto>> findAll() {
+        List<CategoryDto> categories = categoryService.getAllCategories().stream()
+                .map(CategoryDto::from)
+                .collect(Collectors.toList());
+        return ResponseEntity.ok(categories);
+    }
+
+    @Operation(summary = "Get category by ID")
+    @GetMapping("/{id}")
+    public ResponseEntity<CategoryDto> findById(@PathVariable Long id) {
+        Category category = categoryService.findById(id);
+        return ResponseEntity.ok(CategoryDto.from(category));
+    }
+
+    @Operation(summary = "Create category")
+    @PostMapping("/add")
+    public ResponseEntity<CategoryDto> save(@RequestBody CreateCategoryDto createCategoryDto) {
+        Category saved = categoryService.createCategory(createCategoryDto.toCategory());
+        return ResponseEntity.status(HttpStatus.CREATED).body(CategoryDto.from(saved));
+    }
+
+    @Operation(summary = "Update category")
+    @PutMapping("/edit/{id}")
+    public ResponseEntity<CategoryDto> update(@PathVariable Long id, @RequestBody CreateCategoryDto createCategoryDto) {
+        Category updated = categoryService.updateCategory(id, createCategoryDto.toCategory());
+        return ResponseEntity.ok(CategoryDto.from(updated));
+    }
+
+    @Operation(summary = "Delete category")
+    @DeleteMapping("/delete/{id}")
+    public ResponseEntity<Void> deleteById(@PathVariable Long id) {
+        categoryService.deleteCategory(id);
+        return ResponseEntity.noContent().build();
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/EmployeeController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/EmployeeController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/EmployeeController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,45 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.entity.Employee;
+import finki.db.tasty_tabs.service.EmployeeService;
+import finki.db.tasty_tabs.web.dto.AssignmentDto;
+import finki.db.tasty_tabs.web.dto.CreateEmployeeRequest;
+import finki.db.tasty_tabs.web.dto.EmployeeDto;
+import finki.db.tasty_tabs.web.dto.ShiftDto;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/employees") // New Controller
+class EmployeeController {
+
+    private final EmployeeService employeeService;
+
+    public EmployeeController(EmployeeService employeeService) {
+        this.employeeService = employeeService;
+    }
+
+    // This endpoint would be secured in a real application to ensure only managers can access it.
+    @PostMapping("/manager/create")
+    @PreAuthorize("hasRole('MANAGER')")
+    public ResponseEntity<Employee> createEmployee(@RequestBody CreateEmployeeRequest request) {
+        Employee newEmployee = employeeService.createEmployee(request);
+        return ResponseEntity.status(HttpStatus.CREATED).body(newEmployee);
+    }
+
+    @GetMapping()
+    public ResponseEntity<List<EmployeeDto>> getAllEmployees() {
+        List<EmployeeDto> employees = employeeService.getAllEmployees();
+        return ResponseEntity.ok(employees);
+    }
+
+    @GetMapping("/{employeeId}/shifts/next")
+    public ResponseEntity<AssignmentDto> getNextShift(@PathVariable Long employeeId) {
+        AssignmentDto nextShift = employeeService.getNextShiftForEmployee(employeeId);
+        return ResponseEntity.ok(nextShift);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/OrderController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/OrderController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/OrderController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,190 @@
+package finki.db.tasty_tabs.web.controllers;
+import finki.db.tasty_tabs.entity.Order;
+import finki.db.tasty_tabs.service.OrderService;
+import finki.db.tasty_tabs.web.dto.CreateOrderDto;
+import finki.db.tasty_tabs.web.dto.CreateOrderItemDto;
+import finki.db.tasty_tabs.web.dto.OrderDto;
+import finki.db.tasty_tabs.web.dto.OrderItemDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/orders")
+@Tag(name = "Order API", description = "Endpoints for managing orders")
+@RequiredArgsConstructor
+public class OrderController {
+
+    private final OrderService orderService;
+
+    @Operation(summary = "Get all orders (both online and tab)")
+    @GetMapping
+    public List<OrderDto> getAllOrders() {
+        return orderService.findAll().stream()
+                .map(OrderDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get any order by ID")
+    @GetMapping("/{id}")
+    public ResponseEntity<OrderDto> getOrderById(@PathVariable Long id) {
+        return ResponseEntity.ok(OrderDto.from(orderService.findById(id)));
+    }
+
+    @Operation(summary = "Update an existing order")
+    @PutMapping("/{id}")
+    public ResponseEntity<OrderDto> updateOrder(@PathVariable Long id, @RequestBody CreateOrderDto dto) {
+        return ResponseEntity.ok(OrderDto.from(orderService.updateOrder(id, dto)));
+    }
+
+    @Operation(summary = "Delete an order by ID")
+    @DeleteMapping("/{id}")
+    public ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
+        orderService.deleteOrder(id);
+        return ResponseEntity.noContent().build();
+    }
+
+    @Operation(summary = "Calculate total price of an order")
+    @GetMapping("/{id}/total-price")
+    public ResponseEntity<Double> calculateTotalPrice(@PathVariable Long id) {
+        return ResponseEntity.ok(orderService.calculateTotalPrice(id));
+    }
+
+    @Operation(summary = "Update the status of an order")
+    @PatchMapping("/{id}/status")
+    public ResponseEntity<Void> updateOrderStatus(@PathVariable Long id, @RequestBody Map<String, String> status) {
+        orderService.updateOrderStatus(id, status.get("status"));
+        return ResponseEntity.noContent().build();
+    }
+
+    @Operation(summary = "Cancel an order")
+    @PatchMapping("/{orderId}/cancel")
+    public ResponseEntity<OrderDto> cancelOrder(@PathVariable Long orderId) {
+        return ResponseEntity.ok(OrderDto.from(orderService.cancelOrder(orderId)));
+    }
+
+    // Order Item Endpoints
+    @Operation(summary = "Add an item to an existing order")
+    @PostMapping("/{orderId}/items")
+    public ResponseEntity<OrderItemDto> addItemToOrder(@PathVariable Long orderId, @RequestBody CreateOrderItemDto itemDto) {
+        return ResponseEntity.ok(OrderItemDto.from(orderService.addItemToOrder(orderId, itemDto)));
+    }
+
+    @Operation(summary = "Decrease the quantity of a specific order item")
+    @DeleteMapping("/items/{orderItemId}")
+    public ResponseEntity<Void> decreaseOrderItemQuantity(@PathVariable Long orderItemId) {
+        orderService.decreaseOrderItemQuantity(orderItemId);
+        return ResponseEntity.noContent().build();
+    }
+
+    @Operation(summary = "Update an existing order item")
+    @PutMapping("/items/{orderItemId}")
+    public ResponseEntity<OrderItemDto> updateOrderItem(@PathVariable Long orderItemId, @RequestBody CreateOrderItemDto itemDto) {
+        return ResponseEntity.ok(OrderItemDto.from(orderService.updateOrderItem(orderItemId, itemDto)));
+    }
+
+    @Operation(summary = "Delete an order item by ID")
+    @DeleteMapping("/items/{orderItemId}/delete")
+    public ResponseEntity<Void> deleteOrderItem(@PathVariable Long orderItemId) {
+        orderService.deleteOrderItem(orderItemId);
+        return ResponseEntity.noContent().build();
+    }
+
+    @Operation(summary = "Mark an order item as processed")
+    @PatchMapping("/items/{orderItemId}/process")
+    public ResponseEntity<OrderItemDto> processOrderItem(@PathVariable Long orderItemId) {
+        return ResponseEntity.ok(OrderItemDto.from(orderService.processOrderItem(orderItemId)));
+    }
+
+    // Online Order Endpoints
+    @Operation(summary = "Create a new online order for a logged-in customer")
+    @PostMapping("/online")
+    public ResponseEntity<OrderDto> createOnlineOrder(@RequestBody CreateOrderDto dto, Authentication authentication) {
+        String userEmail = authentication.getName();
+        return ResponseEntity.ok(OrderDto.from(orderService.createOnlineOrder(dto, userEmail)));
+    }
+
+    @Operation(summary = "Get all online orders")
+    @GetMapping("/online")
+    public List<OrderDto> getAllOnlineOrders() {
+        return orderService.findAllOnlineOrders().stream()
+                .map(OrderDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get a specific online order by ID")
+    @GetMapping("/online/{id}")
+    public ResponseEntity<OrderDto> getOnlineOrderById(@PathVariable Long id) {
+        return ResponseEntity.ok(OrderDto.from(orderService.findOnlineOrderById(id)));
+    }
+
+    @Operation(summary = "Get all online orders for a specific customer")
+    @GetMapping("/online/customer/{customerId}")
+    public List<OrderDto> getOnlineOrdersByCustomer(@PathVariable Long customerId) {
+        return orderService.findOnlineOrdersByCustomer(customerId).stream()
+                .map(OrderDto::from)
+                .collect(Collectors.toList());
+    }
+
+    // Tab Order Endpoints
+    @Operation(summary = "Create a new tab order for a logged-in front staff member")
+    @PostMapping("/tab")
+    public ResponseEntity<OrderDto> createTabOrder(@RequestBody CreateOrderDto dto, Authentication authentication) {
+        String userEmail = authentication.getName();
+        return ResponseEntity.ok(OrderDto.from(orderService.createTabOrder(dto, userEmail)));
+    }
+
+    @Operation(summary = "Get all tab orders")
+    @GetMapping("/tab")
+    public List<OrderDto> getAllTabOrders() {
+        return orderService.findAllTabOrders().stream()
+                .map(OrderDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get a specific tab order by ID")
+    @GetMapping("/tab/{id}")
+    public ResponseEntity<OrderDto> getTabOrderById(@PathVariable Long id) {
+        return ResponseEntity.ok(OrderDto.from(orderService.findTabOrderById(id)));
+    }
+
+    @Operation(summary = "Get all tab orders for a specific table on a given date (defaults to today)")
+    @GetMapping("/tab/table/{tableNumber}")
+    public List<OrderDto> getTabOrdersByTableAndDate(
+            @PathVariable Integer tableNumber,
+            @RequestParam(required = false, defaultValue = "#{T(java.time.LocalDate).now()}") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
+        return orderService.findTabOrdersByTableAndDate(tableNumber, date).stream()
+                .map(OrderDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Assign a TabOrder to a specific front staff member")
+    @PatchMapping("/tab/{orderId}/assign-staff/{frontStaffId}")
+    public ResponseEntity<OrderDto> assignOrderToStaff(@PathVariable Long orderId, @PathVariable Long frontStaffId) {
+        return ResponseEntity.ok(OrderDto.from(orderService.assignOrderToStaff(orderId, frontStaffId)));
+    }
+    @Operation(summary = "Get all open orders (pending or in-progress)")
+    @GetMapping("/open")
+    public List<OrderDto> getOpenOrders() {
+        return orderService.findOpenOrders().stream()
+                .map(OrderDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get all closed orders (completed, canceled, or delivered)")
+    @GetMapping("/closed")
+    public List<OrderDto> getClosedOrders() {
+        return orderService.findClosedOrders().stream()
+                .map(OrderDto::from)
+                .collect(Collectors.toList());
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/PaymentController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/PaymentController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/PaymentController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,61 @@
+package finki.db.tasty_tabs.web.controllers;
+
+
+import finki.db.tasty_tabs.entity.Payment;
+import finki.db.tasty_tabs.service.PaymentService;
+import finki.db.tasty_tabs.web.dto.CreatePaymentDto;
+import finki.db.tasty_tabs.web.dto.PaymentDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/payments")
+@Tag(name = "Payment API", description = "Endpoints for managing payments")
+@RequiredArgsConstructor
+public class PaymentController {
+
+    private final PaymentService paymentService;
+
+    @Operation(summary = "Create a new payment for an order")
+    @PostMapping
+    public ResponseEntity<PaymentDto> createPayment(@RequestBody CreatePaymentDto dto) {
+        Payment newPayment = paymentService.createPayment(dto);
+        return ResponseEntity.ok(PaymentDto.from(newPayment));
+    }
+
+    @Operation(summary = "Get a payment by its ID")
+    @GetMapping("/{id}")
+    public ResponseEntity<PaymentDto> getPaymentById(@PathVariable Long id) {
+        Payment payment = paymentService.findPaymentById(id);
+        return ResponseEntity.ok(PaymentDto.from(payment));
+    }
+
+    @Operation(summary = "Get a payment by its associated order ID")
+    @GetMapping("/order/{orderId}")
+    public ResponseEntity<PaymentDto> getPaymentByOrderId(@PathVariable Long orderId) {
+        Payment payment = paymentService.findPaymentByOrderId(orderId);
+        return ResponseEntity.ok(PaymentDto.from(payment));
+    }
+
+    @Operation(summary = "Get all payments")
+    @GetMapping
+    public List<PaymentDto> getAllPayments() {
+        return paymentService.findAllPayments().stream()
+                .map(PaymentDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Update an existing payment")
+    @PutMapping("/{id}")
+    public ResponseEntity<PaymentDto> updatePayment(@PathVariable Long id, @RequestBody CreatePaymentDto dto) {
+        Payment updatedPayment = paymentService.updatePayment(id, dto);
+        return ResponseEntity.ok(PaymentDto.from(updatedPayment));
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/ProductController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/ProductController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/ProductController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,70 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.entity.Product;
+import finki.db.tasty_tabs.service.ProductService;
+import finki.db.tasty_tabs.web.dto.CreateProductDto;
+import finki.db.tasty_tabs.web.dto.ProductDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/products")
+@Tag(name = "Product API", description = "Endpoints for managing products")
+public class ProductController {
+
+    private final ProductService productService;
+
+    public ProductController(ProductService productService) {
+        this.productService = productService;
+    }
+
+    @Operation(summary = "Get all products")
+    @GetMapping
+    public ResponseEntity<List<ProductDto>> findAll() {
+        List<ProductDto> products = productService.getAllProducts().stream()
+                .map(ProductDto::from)
+                .collect(Collectors.toList());
+        return ResponseEntity.ok(products);
+    }
+
+    @Operation(summary = "Get product by ID")
+    @GetMapping("/{id}")
+    public ResponseEntity<ProductDto> findById(@PathVariable Long id) {
+        return ResponseEntity.ok(ProductDto.from(productService.findById(id)));
+    }
+
+    @Operation(summary = "Search products by name")
+    @GetMapping("/search")
+    public ResponseEntity<List<ProductDto>> findByName(@RequestParam String name) {
+        List<ProductDto> products = productService.getProductsByName(name).stream()
+                .map(ProductDto::from)
+                .collect(Collectors.toList());
+        return ResponseEntity.ok(products);
+    }
+
+    @Operation(summary = "Create new product")
+    @PostMapping("/add")
+    public ResponseEntity<ProductDto> save(@RequestBody CreateProductDto dto) {
+        return ResponseEntity.status(HttpStatus.CREATED).body(ProductDto.from(productService.createProduct(dto)));
+    }
+
+    @Operation(summary = "Update product")
+    @PutMapping("/edit/{id}")
+    public ResponseEntity<ProductDto> update(@PathVariable Long id, @RequestBody CreateProductDto dto) {
+        var updatedProduct = productService.updateProduct(id, dto);
+        return ResponseEntity.ok(ProductDto.from(updatedProduct));
+    }
+
+    @Operation(summary = "Delete product")
+    @DeleteMapping("/delete/{id}")
+    public ResponseEntity<Void> delete(@PathVariable Long id) {
+        productService.deleteProduct(id);
+        return ResponseEntity.noContent().build();
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/ReservationController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/ReservationController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/ReservationController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,104 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.entity.Reservation;
+import finki.db.tasty_tabs.service.ReservationService;
+import finki.db.tasty_tabs.web.dto.CreateReservationDto;
+import finki.db.tasty_tabs.web.dto.ReservationDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/reservations")
+@Tag(name = "Reservation API", description = "Endpoints for managing reservations")
+@RequiredArgsConstructor
+public class ReservationController {
+
+    private final ReservationService reservationService;
+
+    @Operation(summary = "Get all reservations")
+    @GetMapping
+    public List<ReservationDto> getAll() {
+        return reservationService.getAllReservations()
+                .stream()
+                .map(ReservationDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get reservation by ID")
+    @GetMapping("/{id}")
+    public ResponseEntity<ReservationDto> getById(@PathVariable Long id) {
+        return ResponseEntity.ok(ReservationDto.from(reservationService.getReservationById(id)));
+    }
+
+    @Operation(summary = "Create new reservation")
+    @PostMapping("/add")
+    public ResponseEntity<ReservationDto> create(@RequestBody CreateReservationDto dto, Authentication authentication) {
+        String userEmail = authentication.getName();
+        Reservation reservation = reservationService.createReservation(dto, userEmail);
+        return ResponseEntity.ok(ReservationDto.from(reservation));
+    }
+
+    @Operation(summary = "Update reservation")
+    @PutMapping("/edit/{id}")
+    public ResponseEntity<ReservationDto> update(@PathVariable Long id, @RequestBody CreateReservationDto dto, Authentication authentication) {
+        String userEmail = authentication.getName();
+        Reservation reservation = reservationService.updateReservation(id, dto, userEmail);
+        return ResponseEntity.ok(ReservationDto.from(reservation));
+    }
+
+    @Operation(summary = "Delete reservation")
+    @DeleteMapping("/delete/{id}")
+    public ResponseEntity<Void> delete(@PathVariable Long id) {
+        reservationService.deleteReservation(id);
+        return ResponseEntity.noContent().build();
+    }
+
+    @Operation(summary = "Get all reservations made by the logged-in user")
+    @GetMapping("/myReservations")
+    public List<ReservationDto> getMyReservations(Authentication authentication) {
+        String username = authentication.getName();
+        return reservationService.getAllReservationsByUser(username)
+                .stream()
+                .map(ReservationDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Accept a reservation by a front staff member")
+    @PostMapping("/accept/{reservationId}/table/{tableNumber}")
+    public ResponseEntity<ReservationDto> acceptReservation(
+            @PathVariable Long reservationId,
+            @PathVariable Long tableNumber,
+            Authentication authentication
+    ) {
+        String frontStaffEmail = authentication.getName();
+        reservationService.acceptReservation(reservationId,frontStaffEmail,tableNumber);
+        return ResponseEntity.ok(ReservationDto.from(reservationService.getReservationById(reservationId)));
+    }
+    @Operation(summary = "Get all reservations for today")
+    @GetMapping("/today")
+    public List<ReservationDto> getTodayReservations() {
+        return reservationService.getAllReservationsForToday()
+                .stream()
+                .map(ReservationDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get all reservations for a specific date")
+    @GetMapping("/by-date")
+    public List<ReservationDto> getReservationsByDate(
+            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
+        return reservationService.getAllReservationsForDate(date)
+                .stream()
+                .map(ReservationDto::from)
+                .collect(Collectors.toList());
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/RestaurantTableController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/RestaurantTableController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/RestaurantTableController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,65 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.entity.RestaurantTable;
+import finki.db.tasty_tabs.service.RestaurantTableService;
+import finki.db.tasty_tabs.web.dto.CreateRestaurantTableDto;
+import finki.db.tasty_tabs.web.dto.RestaurantTableDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.http.HttpStatus;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/tables")
+@Tag(name = "Restaurant Table API", description = "Endpoints for managing restaurant tables")
+public class RestaurantTableController {
+
+    private final RestaurantTableService restaurantTableService;
+
+    public RestaurantTableController(RestaurantTableService restaurantTableService) {
+        this.restaurantTableService = restaurantTableService;
+    }
+
+    @Operation(summary = "Get all tables", description = "Retrieves a list of all restaurant tables.")
+    @GetMapping
+    public List<RestaurantTableDto> findAll() {
+        return restaurantTableService.getAll()
+                .stream()
+                .map(RestaurantTableDto::from)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get a table by table number", description = "Finds a table by its table number.")
+    @GetMapping("/{tableNumber}")
+    public ResponseEntity<RestaurantTableDto> findById(@PathVariable Long tableNumber) {
+        return ResponseEntity.ok(RestaurantTableDto.from(restaurantTableService.findById(tableNumber)));
+                }
+
+    @Operation(summary = "Add a new table", description = "Creates a new restaurant table.")
+    @PostMapping("/add")
+    public ResponseEntity<RestaurantTableDto> save(@RequestBody CreateRestaurantTableDto dto) {
+        RestaurantTable newTable = restaurantTableService.createTable(dto.toRestaurantTable());
+        return ResponseEntity.status(HttpStatus.CREATED).body(RestaurantTableDto.from(newTable));
+    }
+
+    @Operation(summary = "Update an existing table", description = "Updates a restaurant table by its table number.")
+    @PutMapping("/edit/{tableNumber}")
+    public ResponseEntity<RestaurantTableDto> update(
+            @PathVariable Long tableNumber,
+            @RequestBody CreateRestaurantTableDto dto
+    ) {
+        RestaurantTable updatedTable = restaurantTableService.updateTable(tableNumber, dto.toRestaurantTable());
+        return ResponseEntity.ok(RestaurantTableDto.from(updatedTable));
+    }
+
+    @Operation(summary = "Delete a table", description = "Deletes a restaurant table by its table number.")
+    @DeleteMapping("/delete/{tableNumber}")
+    public ResponseEntity<Void> deleteById(@PathVariable Long tableNumber) {
+        restaurantTableService.deleteTable(tableNumber);
+        return ResponseEntity.noContent().build();
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/controllers/ShiftController.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/controllers/ShiftController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/controllers/ShiftController.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,67 @@
+package finki.db.tasty_tabs.web.controllers;
+
+import finki.db.tasty_tabs.entity.Shift;
+import finki.db.tasty_tabs.service.ShiftService;
+import finki.db.tasty_tabs.web.dto.CreateShiftDto;
+import finki.db.tasty_tabs.web.dto.ShiftDto;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/shifts")
+@Tag(name = "Shift API", description = "Endpoints for managing work shifts (Manager only)")
+public class ShiftController {
+
+    private final ShiftService shiftService;
+
+    public ShiftController(ShiftService shiftService) {
+        this.shiftService = shiftService;
+    }
+
+    @Operation(summary = "Get all shifts")
+    @GetMapping
+    public List<ShiftDto> getAllShifts() {
+        return shiftService.getAllShifts()
+                .stream()
+                .map(ShiftDto::fromShift)
+                .collect(Collectors.toList());
+    }
+
+    @Operation(summary = "Get shift by ID")
+    @GetMapping("/{id}")
+    public ResponseEntity<ShiftDto> getShiftById(@PathVariable Long id) {
+        Shift shift = shiftService.getShiftById(id);
+        return ResponseEntity.ok(ShiftDto.fromShift(shift));
+    }
+
+    @Operation(summary = "Create a shift (Manager only)")
+    @PostMapping
+    public ResponseEntity<ShiftDto> createShift(@RequestBody CreateShiftDto dto, Authentication authentication) {
+        String username = authentication.getName();
+        Shift shift = shiftService.createShift(dto, username);
+        return new ResponseEntity<>(ShiftDto.fromShift(shift), HttpStatus.CREATED);
+    }
+
+    @Operation(summary = "Update a shift (Manager only)")
+    @PutMapping("/{id}")
+    public ResponseEntity<ShiftDto> updateShift(@PathVariable Long id, @RequestBody CreateShiftDto dto, Authentication authentication) {
+        String username = authentication.getName();
+        Shift updatedShift = shiftService.updateShift(id, dto, username);
+        return ResponseEntity.ok(ShiftDto.fromShift(updatedShift));
+    }
+
+    @Operation(summary = "Delete a shift (Manager only)")
+    @DeleteMapping("/{id}")
+    public ResponseEntity<Void> deleteShift(@PathVariable Long id, Authentication authentication) {
+        String username = authentication.getName();
+        shiftService.deleteShift(id, username);
+        return ResponseEntity.noContent().build();
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/AssignmentDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/AssignmentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/AssignmentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,27 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.Assignment;
+import finki.db.tasty_tabs.entity.Employee;
+import finki.db.tasty_tabs.entity.Manager;
+
+import java.time.LocalDateTime;
+
+public record AssignmentDto(
+        Long id,
+        LocalDateTime clockInTime,
+        LocalDateTime clockOutTime,
+        ManagerDto manager,
+        EmployeeDto employee,
+        ShiftDto shift
+) {
+    public static AssignmentDto fromAssignment(Assignment assignment) {
+        return new AssignmentDto(
+                assignment.getId(),
+                assignment.getClockInTime(),
+                assignment.getClockOutTime(),
+                ManagerDto.from(assignment.getManager()),
+                EmployeeDto.from(assignment.getEmployee()),
+                ShiftDto.fromShiftBasic(assignment.getShift())
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/AuthDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/AuthDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/AuthDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,7 @@
+package finki.db.tasty_tabs.web.dto;
+
+public record AuthDto (
+        String token,
+        UserDto user
+){
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CategoryDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CategoryDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CategoryDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.Category;
+
+public record CategoryDto(
+        Long id,
+        String name,
+        Boolean isAvailable
+) {
+    public static CategoryDto from(Category category) {
+        return new CategoryDto(category.getId(), category.getName(), category.getIsAvailable());
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/ClockInRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/ClockInRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/ClockInRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,11 @@
+package finki.db.tasty_tabs.web.dto;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+
+@Data
+public class ClockInRequest {
+    private Long employeeId;
+    private Long shiftId;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateAssignmentDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateAssignmentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateAssignmentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,24 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.Assignment;
+import finki.db.tasty_tabs.entity.Employee;
+import finki.db.tasty_tabs.entity.Manager;
+import finki.db.tasty_tabs.entity.Shift;
+
+import java.time.LocalDateTime;
+
+public record CreateAssignmentDto(
+        LocalDateTime clockInTime,
+        LocalDateTime clockOutTime,
+        Long employeeId,
+        Long shiftId
+) {
+    public Assignment toAssignment(Employee employee,Shift shift) {
+        return new Assignment(
+                clockInTime,
+                clockOutTime,
+                employee,
+                shift
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateCategoryDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateCategoryDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateCategoryDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.Category;
+
+public record CreateCategoryDto(
+        String name,
+        Boolean isAvailable
+) {
+    public Category toCategory() {
+        return new Category(name, isAvailable);
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateEmployeeRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateEmployeeRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateEmployeeRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,17 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.EmployeeType;
+
+public record CreateEmployeeRequest(
+        String email,
+        String password,
+        String street,
+        String city,
+        String phoneNumber,
+        Double netSalary,
+        Double grossSalary,
+        EmployeeType employeeType,
+        Long staffRoleId, // Only for FrontStaff/BackStaff
+        Double tipPercent // Only for FrontStaff
+) {
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOnlineOrderRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOnlineOrderRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOnlineOrderRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,12 @@
+package finki.db.tasty_tabs.web.dto;
+import lombok.Data;
+import java.time.LocalDateTime;
+import java.util.List;
+
+
+@Data
+public class CreateOnlineOrderRequest {
+    private Long customerId;
+    private String deliveryAddress;
+    private List<OrderItemRequest> items;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,11 @@
+package finki.db.tasty_tabs.web.dto;
+
+import java.util.List;
+
+public record CreateOrderDto(
+        List<CreateOrderItemDto> orderItems,
+        String status,
+        String type, // "online" or "tab"
+        String deliveryAddress, // For OnlineOrder
+        Long tableNumber // For TabOrder
+) { }
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderItemDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderItemDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderItemDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,7 @@
+package finki.db.tasty_tabs.web.dto;
+public record CreateOrderItemDto(
+        Long productId,
+        Integer quantity,
+        Double price,
+        Boolean isProcessed
+) { }
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreatePaymentDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreatePaymentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreatePaymentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.web.dto;
+
+public record CreatePaymentDto(
+        Double tipAmount,
+        String paymentType,
+        Double amount,
+        Long orderId
+) {}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateProductDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateProductDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateProductDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs.web.dto;
+
+public record CreateProductDto(
+        String name,
+        Double price,
+        String taxClass,
+        String description,
+        Boolean manageInventory,
+        Long categoryId,
+        Integer quantity,
+        Integer restockLevel
+) {
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateReservationDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateReservationDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateReservationDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,10 @@
+package finki.db.tasty_tabs.web.dto;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+public record CreateReservationDto(
+        Integer stayLength,
+        LocalDateTime datetime,
+        Integer numberOfPeople
+) {
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateRestaurantTableDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateRestaurantTableDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateRestaurantTableDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,12 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.RestaurantTable;
+
+public record CreateRestaurantTableDto(
+        Long tableNumber,
+        Integer seatCapacity
+) {
+    public RestaurantTable toRestaurantTable(){
+        return new RestaurantTable(tableNumber,seatCapacity);
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateShiftDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateShiftDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateShiftDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,21 @@
+package finki.db.tasty_tabs.web.dto;
+import finki.db.tasty_tabs.entity.Manager;
+import finki.db.tasty_tabs.entity.Shift;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+public record CreateShiftDto(
+        LocalDate date,
+        LocalDateTime start,
+        LocalDateTime end
+) {
+    public Shift toShift(Manager manager) {
+        return new Shift(
+                date,
+                start,
+                end
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateTabOrderRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateTabOrderRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/CreateTabOrderRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,10 @@
+package finki.db.tasty_tabs.web.dto;
+import lombok.Data;
+import java.time.LocalDateTime;
+import java.util.List;
+@Data
+public class CreateTabOrderRequest {
+    private Integer tableNumber;
+    private Long frontStaffId;
+    private List<OrderItemRequest> items;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/EmployeeDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/EmployeeDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/EmployeeDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,30 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.Employee;
+import finki.db.tasty_tabs.entity.UserType;
+
+import java.time.LocalDateTime;
+
+public record EmployeeDto(
+        Long id,
+        String email,
+        String street,
+        String city,
+        String phoneNumber,
+        Double netSalary,
+        Double grossSalary,
+        UserType userType
+) {
+    public static EmployeeDto from(Employee employee) {
+        return new EmployeeDto(
+                employee.getId(),
+                employee.getEmail(),
+                employee.getStreet(),
+                employee.getCity(),
+                employee.getPhoneNumber(),
+                employee.getNetSalary(),
+                employee.getGrossSalary(),
+                employee.getUserType()
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/FrontStaffDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/FrontStaffDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/FrontStaffDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,29 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.FrontStaff;
+
+public record FrontStaffDto(
+        Long id,
+        String email,
+        String street,
+        String city,
+        String phoneNumber,
+        Double netSalary,
+        Double grossSalary,
+        Double tipPercent,
+        String staffRoleName
+) {
+    public static FrontStaffDto from(FrontStaff user) {
+        return new FrontStaffDto(
+                user.getId(),
+                user.getEmail(),
+                user.getStreet(),
+                user.getCity(),
+                user.getPhoneNumber(),
+                user.getNetSalary(),
+                user.getGrossSalary(),
+                user.getTipPercent(),     // Предпоставуваме дека User има tipPercent
+                user.getStaffRole().getName()   // Предпоставуваме дека User има staffRoleName
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/ManagerDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/ManagerDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/ManagerDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs.web.dto;
+import finki.db.tasty_tabs.entity.Manager;
+import lombok.Data;
+import java.time.LocalDateTime;
+import java.util.List;
+public record ManagerDto(
+        Long id,
+        String email
+        ){
+    public static ManagerDto from(Manager manager){
+        return new ManagerDto(manager.getId(), manager.getEmail());
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,68 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.OnlineOrder;
+import finki.db.tasty_tabs.entity.Order;
+import finki.db.tasty_tabs.entity.TabOrder;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public record OrderDto(
+        Long id,
+        LocalDateTime timestamp,
+        String status,
+        String type,
+        String customerName,
+        String deliveryAddress,
+        Long tableNumber,
+        String frontStaffName,
+        List<OrderItemDto> orderItems
+) {
+    public static OrderDto from(Order order) {
+        if (order instanceof OnlineOrder onlineOrder) {
+            return new OrderDto(
+                    onlineOrder.getId(),
+                    onlineOrder.getTimestamp(),
+                    onlineOrder.getStatus(),
+                    "ONLINE",
+                    onlineOrder.getCustomer().getEmail(),
+                    onlineOrder.getDeliveryAddress(),
+                    null,
+                    null,
+                    onlineOrder.getOrderItems().stream()
+                            .map(OrderItemDto::from)
+                            .collect(Collectors.toList())
+            );
+        } else if (order instanceof TabOrder tabOrder) {
+            return new OrderDto(
+                    tabOrder.getId(),
+                    tabOrder.getTimestamp(),
+                    tabOrder.getStatus(),
+                    "TAB",
+                    null,
+                    null,
+                    tabOrder.getRestaurantTable().getTableNumber(),
+                    tabOrder.getFrontStaff().getEmail(),
+                    tabOrder.getOrderItems().stream()
+                            .map(OrderItemDto::from)
+                            .collect(Collectors.toList())
+            );
+        } else {
+            // Handle the base Order entity if needed
+            return new OrderDto(
+                    order.getId(),
+                    order.getTimestamp(),
+                    order.getStatus(),
+                    "base",
+                    null,
+                    null,
+                    null,
+                    null,
+                    order.getOrderItems().stream()
+                            .map(OrderItemDto::from)
+                            .collect(Collectors.toList())
+            );
+        }
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderItemDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderItemDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderItemDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,27 @@
+package finki.db.tasty_tabs.web.dto;
+
+
+import finki.db.tasty_tabs.entity.OrderItem;
+import java.time.LocalDateTime;
+
+public record OrderItemDto(
+        Long id,
+        Integer quantity,
+        Double price,
+        Boolean isProcessed,
+        LocalDateTime timestamp,
+        Long productId,
+        String productName
+) {
+    public static OrderItemDto from(OrderItem orderItem) {
+        return new OrderItemDto(
+                orderItem.getId(),
+                orderItem.getQuantity(),
+                orderItem.getPrice(),
+                orderItem.getIsProcessed(),
+                orderItem.getTimestamp(),
+                orderItem.getProduct().getId(),
+                orderItem.getProduct().getName()
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderItemRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderItemRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/OrderItemRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,9 @@
+package finki.db.tasty_tabs.web.dto;
+import lombok.Data;
+import java.time.LocalDateTime;
+import java.util.List;
+@Data
+public class OrderItemRequest {
+    private Long productId;
+    private int quantity;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/PaymentDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/PaymentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/PaymentDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,25 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.Payment;
+
+import java.time.LocalDateTime;
+
+public record PaymentDto(
+        Long id,
+        Double tipAmount,
+        LocalDateTime timestamp,
+        String paymentType,
+        Double amount,
+        Long orderId
+) {
+    public static PaymentDto from(Payment payment) {
+        return new PaymentDto(
+                payment.getId(),
+                payment.getTipAmount(),
+                payment.getTimestamp(),
+                payment.getPaymentType(),
+                payment.getAmount(),
+                payment.getOrder().getId()
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/ProductDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/ProductDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/ProductDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,25 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.Product;
+
+public record ProductDto(
+        Long id,
+        String name,
+        Double price,
+        String taxClass,
+        String description,
+        Boolean manageInventory,
+        CategoryDto category
+) {
+    public static ProductDto from(Product product) {
+        return new ProductDto(product.getId(),
+                product.getName(),
+                product.getPrice(),
+                product.getTaxClass(),
+                product.getDescription(),
+                product.getManageInventory(),
+                CategoryDto.from(product.getCategory())
+                );
+    }
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/ReservationDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/ReservationDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/ReservationDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,24 @@
+package finki.db.tasty_tabs.web.dto;
+import finki.db.tasty_tabs.entity.Reservation;
+import lombok.Data;
+import java.time.LocalDateTime;
+import java.util.List;
+public record ReservationDto(
+        Long id,
+        Integer stayLength,
+        LocalDateTime datetime,
+        LocalDateTime creationTimestamp,
+        Integer numberOfPeople,
+        String email
+) {
+    public static ReservationDto from(Reservation reservation) {
+        return new ReservationDto(
+                reservation.getId(),
+                reservation.getStayLength(),
+                reservation.getDatetime(),
+                reservation.getCreationTimestamp(),
+                reservation.getNumberOfPeople(),
+                reservation.getUser().getEmail()
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/RestaurantTableDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/RestaurantTableDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/RestaurantTableDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,12 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.RestaurantTable;
+
+public record RestaurantTableDto(
+        Long tableNumber,
+        Integer seatCapacity
+) {
+    public static RestaurantTableDto from(RestaurantTable table){
+        return new RestaurantTableDto(table.getTableNumber(), table.getSeatCapacity());
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/ShiftDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/ShiftDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/ShiftDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,40 @@
+package finki.db.tasty_tabs.web.dto;
+import finki.db.tasty_tabs.entity.Manager;
+import finki.db.tasty_tabs.entity.Shift;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+public record ShiftDto(
+        Long id,
+        LocalDate date,
+        LocalDateTime start,
+        LocalDateTime end,
+        ManagerDto manager,
+        List<AssignmentDto> assignments
+) {
+    public static ShiftDto fromShift(Shift shift) {
+        return new ShiftDto(
+                shift.getId(),
+                shift.getDate(),
+                shift.getStart(),
+                shift.getEnd(),
+                ManagerDto.from(shift.getManager()),
+                shift.getAssignments().stream()
+                        .map(AssignmentDto::fromAssignment)
+                        .toList()
+        );
+    }
+    public static ShiftDto fromShiftBasic(Shift shift) {
+        return new ShiftDto(
+                shift.getId(),
+                shift.getDate(),
+                shift.getStart(),
+                shift.getEnd(),
+                ManagerDto.from(shift.getManager()),
+                null
+        );
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/TransferTabRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/TransferTabRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/TransferTabRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.web.dto;
+import lombok.Data;
+import java.time.LocalDateTime;
+import java.util.List;
+@Data
+public class TransferTabRequest {
+    private Long newFrontStaffId;
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/UserDto.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/UserDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/UserDto.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,24 @@
+package finki.db.tasty_tabs.web.dto;
+
+import finki.db.tasty_tabs.entity.User;
+import finki.db.tasty_tabs.entity.UserType;
+
+public record UserDto(
+        Long id,
+        String email,
+        String street,
+        String city,
+        String phoneNumber,
+        UserType userType
+) {
+    public static UserDto from(User user) {
+        return new UserDto(
+                user.getId(),
+                user.getEmail(),
+                user.getStreet(),
+                user.getCity(),
+                user.getPhoneNumber(),
+                user.getUserType()
+        );
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/request/AuthRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/request/AuthRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/request/AuthRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,7 @@
+package finki.db.tasty_tabs.web.dto.request;
+
+public record AuthRequest(
+        String username,
+        String password
+) {
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/dto/request/RegisterRequest.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/dto/request/RegisterRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/dto/request/RegisterRequest.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,17 @@
+package finki.db.tasty_tabs.web.dto.request;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Data
+public class RegisterRequest {
+    @NotNull(message = "Email is required")
+    private String email;
+    @NotNull(message = "Password is required")
+    private String password;
+    private String passwordConfirmation;
+    private String firstName;
+    private String lastName;
+
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/exception/FilterExceptionHandler.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/exception/FilterExceptionHandler.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/exception/FilterExceptionHandler.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,75 @@
+package finki.db.tasty_tabs.web.exception;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.jsonwebtoken.ExpiredJwtException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatusCode;
+import org.springframework.http.ProblemDetail;
+import org.springframework.security.authentication.AccountStatusException;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authorization.AuthorizationDeniedException;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.AccessDeniedException;
+import java.security.SignatureException;
+
+@Slf4j
+public class FilterExceptionHandler {
+
+    // Handle an exception within a filter using the same ErrorResponse structure.
+    public static void handleException(HttpServletRequest request,
+                                       HttpServletResponse response,
+                                       Exception exception) throws IOException {
+        // Convert exception -> ErrorResponse just like your GlobalExceptionHandler.
+        ProblemDetail errorDetail = createErrorResponse(exception);
+        errorDetail.setInstance(URI.create(request.getRequestURI()));
+
+        // Write the ErrorResponse as JSON to response
+        response.setStatus(errorDetail.getStatus());
+        response.setContentType("application/json");
+
+        // For JSON serialization, you can use Jackson's ObjectMapper if available.
+        String json = new ObjectMapper().writeValueAsString(errorDetail);
+        response.getWriter().write(json);
+        response.getWriter().flush();
+    }
+
+    private static ProblemDetail createErrorResponse(Exception exception) {
+        ProblemDetail detail = null;
+
+        if (exception instanceof BadCredentialsException) {
+            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(401), exception.getMessage());
+            detail.setProperty("description", "The username or password is incorrect");
+        } else if (exception instanceof AccountStatusException) {
+            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            detail.setProperty("description", "The account is locked");
+        } else if (exception instanceof AccessDeniedException) {
+            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            detail.setProperty("description", "You are not authorized to access this resource");
+        } else if (exception instanceof SignatureException) {
+            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            detail.setProperty("description", "The JWT signature is invalid");
+        } else if (exception instanceof ExpiredJwtException) {
+            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(401), exception.getMessage());
+            detail.setProperty("description", "The JWT token has expired");
+        } else if (exception instanceof AuthorizationDeniedException) {
+            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            detail.setProperty("description", "You are not authorized to access this resource");
+        }
+
+        if (detail == null) {
+            // Unknown/unhandled exception
+            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
+            detail.setProperty("description", "Unknown internal server error.");
+        }
+
+//        log.warn("An exception occurred: {}", exception.getMessage(), exception);
+
+        return detail;
+    }
+}
+
+
Index: backend/src/main/java/finki/db/tasty_tabs/web/exception/GlobalExceptionHandler.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/exception/GlobalExceptionHandler.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/exception/GlobalExceptionHandler.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,100 @@
+package finki.db.tasty_tabs.web.exception;
+
+import finki.db.tasty_tabs.entity.exceptions.DomainException;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.JwtException;
+import io.jsonwebtoken.security.SignatureException;
+import io.swagger.v3.oas.annotations.Hidden;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatusCode;
+import org.springframework.http.ProblemDetail;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.authentication.AccountStatusException;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authorization.AuthorizationDeniedException;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+@Hidden
+@Slf4j
+public class GlobalExceptionHandler {
+
+    @ExceptionHandler({JwtException.class, AuthenticationException.class, SignatureException.class, AccessDeniedException.class})
+    public ProblemDetail handleSecurityExceptions(Exception exception) {
+        ProblemDetail errorDetail = null;
+
+        log.warn("Security exception: {}", exception.getMessage());
+        if (exception instanceof BadCredentialsException) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(401), exception.getMessage());
+            errorDetail.setProperty("description", "The username or password is incorrect");
+
+        }
+        if (exception instanceof IllegalStateException) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(400), exception.getMessage());
+            errorDetail.setProperty("description", "Invalid operation: " + exception.getMessage());
+        }
+
+        if (exception instanceof AccountStatusException) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            errorDetail.setProperty("description", "The account is locked");
+        }
+
+        if (exception instanceof AuthorizationDeniedException){
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            errorDetail.setProperty("description", "You are not authorized to access this resource");
+        }
+
+        if (exception instanceof AccessDeniedException) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            errorDetail.setProperty("description", "You are not authorized to access this resource");
+        }
+        if (exception instanceof SecurityException) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            errorDetail.setProperty("description", "You are not authorized to perform this action");
+        }
+
+        if (exception instanceof SignatureException) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            errorDetail.setProperty("description", "The JWT signature is invalid");
+        }
+
+        if (exception instanceof ExpiredJwtException) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
+            errorDetail.setProperty("description", "The JWT token has expired");
+        }
+
+        if (errorDetail == null) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
+            errorDetail.setProperty("description", "Unknown internal server error.");
+        }
+
+        return errorDetail;
+    }
+
+    @ExceptionHandler(DomainException.class)
+    public ProblemDetail handleDomainExceptions(DomainException exception) {
+        ProblemDetail errorDetail = null;
+
+        log.warn("Domain exception: {}", exception.getMessage());
+
+        if (errorDetail == null) {
+            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
+            errorDetail.setProperty("description", "Unknown internal server error.");
+        }
+
+        return errorDetail;
+    }
+
+
+    @ExceptionHandler(Exception.class)
+    public ProblemDetail handleAllExceptions(Exception exception) {
+        ProblemDetail errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
+        errorDetail.setProperty("description", "Unknown internal server error.");
+
+        log.error("Unexpected exception: {}", exception.getMessage(), exception);
+
+        return errorDetail;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/filter/HttpLoggingFilter.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/filter/HttpLoggingFilter.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/filter/HttpLoggingFilter.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,59 @@
+package finki.db.tasty_tabs.web.filter;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+@Component
+@Slf4j
+public class HttpLoggingFilter extends OncePerRequestFilter {
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest req,
+                                    HttpServletResponse resp,
+                                    FilterChain chain)
+            throws ServletException, IOException {
+
+        long start = System.currentTimeMillis();
+        try {
+            chain.doFilter(req, resp);
+        } finally {
+            MDC.put("userId", resolveUserId());
+
+            // — compute duration —
+            long timeMs = System.currentTimeMillis() - start;
+            MDC.put("timeMs", String.valueOf(timeMs));
+
+            // — log it —
+//            log.info("Request: {} {} {} from {} – {}ms",
+//                    resp.getStatus(),
+//                    req.getMethod(),
+//                    req.getRequestURI(),
+//                    req.getRemoteAddr(),
+//                    timeMs);
+
+            // — cleanup —
+            MDC.clear();
+        }
+    }
+
+    private String resolveUserId() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
+            return "ANONYMOUS";
+        }
+        return ((UserDetails) authentication.getPrincipal()).getUsername();
+    }
+}
+
Index: backend/src/main/java/finki/db/tasty_tabs/web/filter/JwtAuthenticationFilter.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/filter/JwtAuthenticationFilter.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/filter/JwtAuthenticationFilter.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,89 @@
+package finki.db.tasty_tabs.web.filter;
+
+import finki.db.tasty_tabs.utils.JwtProvider;
+import finki.db.tasty_tabs.web.exception.FilterExceptionHandler;
+import finki.db.tasty_tabs.web.security.CustomUserDetailsService;
+import finki.db.tasty_tabs.web.security.PublicUrlProvider;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.JwtException;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.authorization.AuthorizationDeniedException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+@Component
+@Slf4j
+public class JwtAuthenticationFilter extends OncePerRequestFilter {
+    private final JwtProvider jwtProvider;
+    private final CustomUserDetailsService userDetailsService;
+    private final PublicUrlProvider publicUrlProvider;
+    private final AntPathMatcher pathMatcher = new AntPathMatcher();
+
+    // Update the constructor
+    public JwtAuthenticationFilter(JwtProvider jwtProvider, CustomUserDetailsService userDetailsService, PublicUrlProvider publicUrlProvider) {
+        this.jwtProvider = jwtProvider;
+        this.userDetailsService = userDetailsService;
+        this.publicUrlProvider = publicUrlProvider;
+    }
+
+    // --- NEW METHOD ---
+    @Override
+    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
+        // This method tells Spring to SKIP this filter entirely if the path matches.
+        return publicUrlProvider.getPublicPaths().stream()
+                .anyMatch(p -> (pathMatcher.match(p, request.getServletPath()) && "GET".equalsIgnoreCase(request.getMethod())) || ("/api/auth/login".equals(request.getServletPath()) && "POST".equalsIgnoreCase(request.getMethod())) || ("/api/auth/register".equals(request.getServletPath()) && "POST".equalsIgnoreCase(request.getMethod())));
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request,
+                                    HttpServletResponse response,
+                                    FilterChain filterChain) throws ServletException, IOException {
+        try {
+            String token = resolveToken(request);
+            Claims claims = jwtProvider.validateToken(token);
+            if (claims != null) {
+                String email = claims.getSubject();
+                UserDetails userDetails = userDetailsService.loadUserByUserId(email);
+
+                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
+                        userDetails, null, userDetails.getAuthorities());
+                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+
+                SecurityContextHolder.getContext().setAuthentication(authentication);
+                log.debug("JWT token validated");
+            }
+            filterChain.doFilter(request, response);
+        } catch (ExpiredJwtException e) {
+            log.debug("JWT token expired: {}", e.getMessage());
+            FilterExceptionHandler.handleException(request, response, e);
+        } catch (AuthorizationDeniedException e) {
+//            log.debug("Authorization denied: {}", e.getMessage());
+            FilterExceptionHandler.handleException(request, response, e);
+        } catch (JwtException e) {
+//            log.debug("JWT token invalid: {}", e.getMessage());
+            filterChain.doFilter(request, response);
+        } catch (Exception e) {
+            FilterExceptionHandler.handleException(request, response, e);
+        }
+    }
+
+    private String resolveToken(HttpServletRequest request) {
+        String bearerToken = request.getHeader("Authorization");
+        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
+            return bearerToken.substring(7);
+        }
+        return null;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/security/CustomUserDetailsService.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/security/CustomUserDetailsService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/security/CustomUserDetailsService.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+package finki.db.tasty_tabs.web.security;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+
+public interface CustomUserDetailsService extends UserDetailsService {
+    UserDetails loadUserByUserId(String email);
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/security/PublicUrlProvider.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/security/PublicUrlProvider.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/security/PublicUrlProvider.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,19 @@
+package finki.db.tasty_tabs.web.security;
+
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class PublicUrlProvider {
+    // This list should exactly match the permitAll() paths in your SecurityConfig
+    private static final List<String> PUBLIC_PATHS = List.of(
+            "/swagger-ui/**",
+            "/v3/api-docs/**",
+            "/api/categories/**"
+    );
+
+    public List<String> getPublicPaths() {
+        return PUBLIC_PATHS;
+    }
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/security/SecurityConfig.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/security/SecurityConfig.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/security/SecurityConfig.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,75 @@
+package finki.db.tasty_tabs.web.security;
+
+import finki.db.tasty_tabs.web.filter.JwtAuthenticationFilter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+import java.util.Arrays;
+import java.util.List;
+
+@Configuration
+@EnableWebSecurity
+@EnableMethodSecurity
+public class SecurityConfig {
+    @Autowired
+    private JwtAuthenticationFilter jwtAuthenticationFilter;
+
+    @Bean
+    public SecurityFilterChain securityFilterChain(HttpSecurity http, PublicUrlProvider publicUrlProvider) throws Exception {
+        http
+                .csrf(AbstractHttpConfigurer::disable)
+                .cors(cors -> cors.configurationSource(corsConfigurationSource())) // Enable CORS
+                .authorizeHttpRequests(authorize -> authorize
+                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
+                        .requestMatchers(HttpMethod.GET, publicUrlProvider.getPublicPaths().toArray(new String[0])).permitAll()
+                        .requestMatchers("/api/auth/login").permitAll()
+                        .requestMatchers("/api/auth/register").permitAll()
+                        .anyRequest().authenticated()
+                )
+                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
+
+        return http.build();
+    }
+
+    @Bean
+    public CorsConfigurationSource corsConfigurationSource() {
+        CorsConfiguration config = new CorsConfiguration();
+        config.setAllowedOrigins(List.of("*")); // Or specific origins
+        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
+        config.setAllowedHeaders(List.of("*"));
+        config.setAllowCredentials(false);
+        config.setMaxAge(3600L);
+
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", config);
+        return source;
+    }
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
+        return authenticationConfiguration.getAuthenticationManager();
+    }
+
+}
Index: backend/src/main/java/finki/db/tasty_tabs/web/security/UserDetailsServiceImpl.java
===================================================================
--- backend/src/main/java/finki/db/tasty_tabs/web/security/UserDetailsServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/java/finki/db/tasty_tabs/web/security/UserDetailsServiceImpl.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,76 @@
+package finki.db.tasty_tabs.web.security;
+
+import finki.db.tasty_tabs.entity.*;
+import finki.db.tasty_tabs.repository.UserRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Slf4j
+@Service
+public class UserDetailsServiceImpl implements CustomUserDetailsService {
+    @Autowired
+    private UserRepository userRepository;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+//        log.debug("Loading user by username: {}", username);
+        User user = userRepository.findByEmail(username)
+                .orElseThrow(() -> new UsernameNotFoundException("User not found with email: " + username));
+
+        return getUserDetails(user);
+    }
+
+    @Override
+    public UserDetails loadUserByUserId(String email) {
+        log.debug("Loading user by ID: {}", email);
+        User user = userRepository.findByEmail(email)
+                .orElseThrow(() -> new UsernameNotFoundException("User not found with ID: " + email));
+
+        return getUserDetails(user);
+    }
+
+    private UserDetails getUserDetails(User user){
+
+
+        // Convert roles to Spring Security's authorities
+        Set<GrantedAuthority> authorities = new HashSet<>();
+        GrantedAuthority grantedAuthority = getGrantedAuthority(user);
+
+        authorities.add(grantedAuthority);
+        log.debug("Applying role {} to user {}", grantedAuthority.getAuthority(), user.getId());
+
+        return new org.springframework.security.core.userdetails.User(
+                user.getEmail(),
+                user.getPassword(),
+                authorities
+        );
+    }
+
+    private static GrantedAuthority getGrantedAuthority(User user) {
+        GrantedAuthority grantedAuthority;
+
+        if(user instanceof Employee){
+            if(user instanceof Manager){
+                grantedAuthority = new SimpleGrantedAuthority("ROLE_MANAGER");
+            } else if(user instanceof FrontStaff){
+                grantedAuthority = new SimpleGrantedAuthority("ROLE_FRONT_STAFF");
+            } else if (user instanceof BackStaff){
+                grantedAuthority = new SimpleGrantedAuthority("ROLE_BACKSTAFF");
+            } else {
+                grantedAuthority = new SimpleGrantedAuthority("ROLE_EMPLOYEE");
+            }
+        } else{
+            grantedAuthority = new SimpleGrantedAuthority("ROLE_CUSTOMER");
+        }
+        return grantedAuthority;
+    }
+}
+
Index: backend/src/main/resources/application-test.properties
===================================================================
--- backend/src/main/resources/application-test.properties	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/resources/application-test.properties	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,7 @@
+spring.datasource.url=jdbc:postgresql://localhost:5435/spring_boot_db
+spring.datasource.username=springuser
+spring.datasource.password=springpassword
+spring.datasource.driver-class-name=org.postgresql.Driver
+spring.jpa.hibernate.ddl-auto=none
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+spring.flyway.enabled=false
Index: backend/src/main/resources/application.properties
===================================================================
--- backend/src/main/resources/application.properties	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/resources/application.properties	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,15 @@
+spring.application.name=Tasty Tabs
+spring.datasource.url=jdbc:postgresql://localhost:5434/db_202425z_va_prj_tasty_tabs
+spring.datasource.username=db_202425z_va_prj_tasty_tabs_owner
+spring.datasource.password=99e003badb51
+#spring.profiles.active=test
+springdoc.api-docs.enabled=true
+springdoc.swagger-ui.enabled=true
+jwt.secret=e249a8adbb3572a23f1520e69573aab8bc4b2eaf0bfab9c7a8d118a0c5d799aa
+jwt.expiration=86400000
+
+logging.level.finki=DEBUG
+logging.level.org.springframework=DEBUG
+
+spring.flyway.enabled=false
+spring.flyway.baseline-on-migrate=false
Index: backend/src/main/resources/logback-spring.xml
===================================================================
--- backend/src/main/resources/logback-spring.xml	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/main/resources/logback-spring.xml	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p)
+                %clr([${spring.application.name:-},%X{traceId:-},%X{spanId:-}]){yellow} %clr([%t]){faint}
+                %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
+            </pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="STDOUT"/>
+    </root>
+
+    <logger name="finki.db.tasty_tabs" level="DEBUG"/>
+    <logger name="org.springframework" level="WARN"/>
+    <logger name="org.hibernate.SQL" level="WARN"/>
+    <logger name="org.hibernate.type.descriptor.sql" level="WARN"/>
+</configuration>
Index: backend/src/test/java/finki/db/tasty_tabs/TastyTabsApplicationTests.java
===================================================================
--- backend/src/test/java/finki/db/tasty_tabs/TastyTabsApplicationTests.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ backend/src/test/java/finki/db/tasty_tabs/TastyTabsApplicationTests.java	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+package finki.db.tasty_tabs;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TastyTabsApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}
Index: cker-compose.yml
===================================================================
--- docker-compose.yml	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,18 +1,0 @@
-version: '3.8'
-
-services:
-  db:
-    image: postgres:15.5
-    restart: always
-    environment:
-      POSTGRES_USER: springuser
-      POSTGRES_PASSWORD: springpassword
-      POSTGRES_DB: spring_boot_db
-    volumes:
-      - db_data:/var/lib/postgresql/data
-      - ./01.init.sql:/docker-entrypoint-initdb.d/init.sql
-    ports:
-      - "5435:5432"
-
-volumes:
-  db_data:
Index: frontend/.gitignore
===================================================================
--- frontend/.gitignore	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/.gitignore	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
Index: frontend/README.md
===================================================================
--- frontend/README.md	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/README.md	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,69 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
+
+```js
+export default tseslint.config([
+  globalIgnores(['dist']),
+  {
+    files: ['**/*.{ts,tsx}'],
+    extends: [
+      // Other configs...
+
+      // Remove tseslint.configs.recommended and replace with this
+      ...tseslint.configs.recommendedTypeChecked,
+      // Alternatively, use this for stricter rules
+      ...tseslint.configs.strictTypeChecked,
+      // Optionally, add this for stylistic rules
+      ...tseslint.configs.stylisticTypeChecked,
+
+      // Other configs...
+    ],
+    languageOptions: {
+      parserOptions: {
+        project: ['./tsconfig.node.json', './tsconfig.app.json'],
+        tsconfigRootDir: import.meta.dirname,
+      },
+      // other options...
+    },
+  },
+])
+```
+
+You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
+
+```js
+// eslint.config.js
+import reactX from 'eslint-plugin-react-x'
+import reactDom from 'eslint-plugin-react-dom'
+
+export default tseslint.config([
+  globalIgnores(['dist']),
+  {
+    files: ['**/*.{ts,tsx}'],
+    extends: [
+      // Other configs...
+      // Enable lint rules for React
+      reactX.configs['recommended-typescript'],
+      // Enable lint rules for React DOM
+      reactDom.configs.recommended,
+    ],
+    languageOptions: {
+      parserOptions: {
+        project: ['./tsconfig.node.json', './tsconfig.app.json'],
+        tsconfigRootDir: import.meta.dirname,
+      },
+      // other options...
+    },
+  },
+])
+```
Index: frontend/eslint.config.js
===================================================================
--- frontend/eslint.config.js	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/eslint.config.js	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,23 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+import { globalIgnores } from 'eslint/config'
+
+export default tseslint.config([
+  globalIgnores(['dist']),
+  {
+    files: ['**/*.{ts,tsx}'],
+    extends: [
+      js.configs.recommended,
+      tseslint.configs.recommended,
+      reactHooks.configs['recommended-latest'],
+      reactRefresh.configs.vite,
+    ],
+    languageOptions: {
+      ecmaVersion: 2020,
+      globals: globals.browser,
+    },
+  },
+])
Index: frontend/index.html
===================================================================
--- frontend/index.html	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/index.html	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,13 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Vite + React + TS</title>
+  </head>
+  <body>
+    <div id="root"></div>
+    <script type="module" src="/src/main.tsx"></script>
+  </body>
+</html>
Index: frontend/package-lock.json
===================================================================
--- frontend/package-lock.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/package-lock.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,4347 @@
+{
+  "name": "tasty-tabs-admin",
+  "version": "0.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "tasty-tabs-admin",
+      "version": "0.0.0",
+      "dependencies": {
+        "@hookform/resolvers": "^5.2.1",
+        "@tailwindcss/vite": "^4.1.12",
+        "axios": "^1.11.0",
+        "react": "^19.1.1",
+        "react-dom": "^19.1.1",
+        "react-hook-form": "^7.62.0",
+        "react-router-dom": "^7.8.2",
+        "tailwindcss": "^4.1.12",
+        "zod": "^4.1.1"
+      },
+      "devDependencies": {
+        "@eslint/js": "^9.33.0",
+        "@types/react": "^19.1.10",
+        "@types/react-dom": "^19.1.7",
+        "@vitejs/plugin-react": "^5.0.0",
+        "eslint": "^9.33.0",
+        "eslint-plugin-react-hooks": "^5.2.0",
+        "eslint-plugin-react-refresh": "^0.4.20",
+        "globals": "^16.3.0",
+        "typescript": "~5.8.3",
+        "typescript-eslint": "^8.39.1",
+        "vite": "^7.1.2"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+      "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+      "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
+      "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.28.3",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz",
+      "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.28.3",
+        "@babel/helper-compilation-targets": "^7.27.2",
+        "@babel/helper-module-transforms": "^7.28.3",
+        "@babel/helpers": "^7.28.3",
+        "@babel/parser": "^7.28.3",
+        "@babel/template": "^7.27.2",
+        "@babel/traverse": "^7.28.3",
+        "@babel/types": "^7.28.2",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.28.3",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
+      "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.28.3",
+        "@babel/types": "^7.28.2",
+        "@jridgewell/gen-mapping": "^0.3.12",
+        "@jridgewell/trace-mapping": "^0.3.28",
+        "jsesc": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+      "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/compat-data": "^7.27.2",
+        "@babel/helper-validator-option": "^7.27.1",
+        "browserslist": "^4.24.0",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-globals": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+      "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+      "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/traverse": "^7.27.1",
+        "@babel/types": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.28.3",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
+      "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "@babel/traverse": "^7.28.3"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-plugin-utils": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+      "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+      "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.28.3",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz",
+      "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.28.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.28.3",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
+      "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.28.2"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-react-jsx-self": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+      "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-react-jsx-source": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+      "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+      "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/parser": "^7.27.2",
+        "@babel/types": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.28.3",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
+      "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.28.3",
+        "@babel/helper-globals": "^7.28.0",
+        "@babel/parser": "^7.28.3",
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.28.2",
+        "debug": "^4.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.28.2",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
+      "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
+      "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz",
+      "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz",
+      "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz",
+      "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz",
+      "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz",
+      "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz",
+      "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz",
+      "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz",
+      "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz",
+      "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz",
+      "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz",
+      "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz",
+      "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==",
+      "cpu": [
+        "mips64el"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz",
+      "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz",
+      "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz",
+      "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==",
+      "cpu": [
+        "s390x"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz",
+      "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz",
+      "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz",
+      "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz",
+      "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz",
+      "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openharmony-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz",
+      "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openharmony"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz",
+      "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz",
+      "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz",
+      "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz",
+      "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+      "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "eslint-visitor-keys": "^3.4.3"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint-community/regexpp": {
+      "version": "4.12.1",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+      "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@eslint/config-array": {
+      "version": "0.21.0",
+      "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
+      "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/object-schema": "^2.1.6",
+        "debug": "^4.3.1",
+        "minimatch": "^3.1.2"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/config-helpers": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
+      "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/core": {
+      "version": "0.15.2",
+      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
+      "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@types/json-schema": "^7.0.15"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/eslintrc": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+      "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ajv": "^6.12.4",
+        "debug": "^4.3.2",
+        "espree": "^10.0.1",
+        "globals": "^14.0.0",
+        "ignore": "^5.2.0",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^4.1.0",
+        "minimatch": "^3.1.2",
+        "strip-json-comments": "^3.1.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint/eslintrc/node_modules/globals": {
+      "version": "14.0.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+      "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@eslint/js": {
+      "version": "9.34.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz",
+      "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://eslint.org/donate"
+      }
+    },
+    "node_modules/@eslint/object-schema": {
+      "version": "2.1.6",
+      "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+      "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/plugin-kit": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
+      "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/core": "^0.15.2",
+        "levn": "^0.4.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@hookform/resolvers": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.1.tgz",
+      "integrity": "sha512-u0+6X58gkjMcxur1wRWokA7XsiiBJ6aK17aPZxhkoYiK5J+HcTx0Vhu9ovXe6H+dVpO6cjrn2FkJTryXEMlryQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@standard-schema/utils": "^0.3.0"
+      },
+      "peerDependencies": {
+        "react-hook-form": "^7.55.0"
+      }
+    },
+    "node_modules/@humanfs/core": {
+      "version": "0.19.1",
+      "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+      "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18.0"
+      }
+    },
+    "node_modules/@humanfs/node": {
+      "version": "0.16.6",
+      "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+      "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@humanfs/core": "^0.19.1",
+        "@humanwhocodes/retry": "^0.3.0"
+      },
+      "engines": {
+        "node": ">=18.18.0"
+      }
+    },
+    "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+      "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/module-importer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=12.22"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/retry": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+      "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@isaacs/fs-minipass": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+      "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+      "license": "ISC",
+      "dependencies": {
+        "minipass": "^7.0.4"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+      "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "node_modules/@jridgewell/remapping": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+      "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+      "license": "MIT"
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.30",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
+      "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@rolldown/pluginutils": {
+      "version": "1.0.0-beta.32",
+      "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz",
+      "integrity": "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.48.1.tgz",
+      "integrity": "sha512-rGmb8qoG/zdmKoYELCBwu7vt+9HxZ7Koos3pD0+sH5fR3u3Wb/jGcpnqxcnWsPEKDUyzeLSqksN8LJtgXjqBYw==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.48.1.tgz",
+      "integrity": "sha512-4e9WtTxrk3gu1DFE+imNJr4WsL13nWbD/Y6wQcyku5qadlKHY3OQ3LJ/INrrjngv2BJIHnIzbqMk1GTAC2P8yQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.48.1.tgz",
+      "integrity": "sha512-+XjmyChHfc4TSs6WUQGmVf7Hkg8ferMAE2aNYYWjiLzAS/T62uOsdfnqv+GHRjq7rKRnYh4mwWb4Hz7h/alp8A==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.48.1.tgz",
+      "integrity": "sha512-upGEY7Ftw8M6BAJyGwnwMw91rSqXTcOKZnnveKrVWsMTF8/k5mleKSuh7D4v4IV1pLxKAk3Tbs0Lo9qYmii5mQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.48.1.tgz",
+      "integrity": "sha512-P9ViWakdoynYFUOZhqq97vBrhuvRLAbN/p2tAVJvhLb8SvN7rbBnJQcBu8e/rQts42pXGLVhfsAP0k9KXWa3nQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.48.1.tgz",
+      "integrity": "sha512-VLKIwIpnBya5/saccM8JshpbxfyJt0Dsli0PjXozHwbSVaHTvWXJH1bbCwPXxnMzU4zVEfgD1HpW3VQHomi2AQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.48.1.tgz",
+      "integrity": "sha512-3zEuZsXfKaw8n/yF7t8N6NNdhyFw3s8xJTqjbTDXlipwrEHo4GtIKcMJr5Ed29leLpB9AugtAQpAHW0jvtKKaQ==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.48.1.tgz",
+      "integrity": "sha512-leo9tOIlKrcBmmEypzunV/2w946JeLbTdDlwEZ7OnnsUyelZ72NMnT4B2vsikSgwQifjnJUbdXzuW4ToN1wV+Q==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.48.1.tgz",
+      "integrity": "sha512-Vy/WS4z4jEyvnJm+CnPfExIv5sSKqZrUr98h03hpAMbE2aI0aD2wvK6GiSe8Gx2wGp3eD81cYDpLLBqNb2ydwQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.48.1.tgz",
+      "integrity": "sha512-x5Kzn7XTwIssU9UYqWDB9VpLpfHYuXw5c6bJr4Mzv9kIv242vmJHbI5PJJEnmBYitUIfoMCODDhR7KoZLot2VQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.48.1.tgz",
+      "integrity": "sha512-yzCaBbwkkWt/EcgJOKDUdUpMHjhiZT/eDktOPWvSRpqrVE04p0Nd6EGV4/g7MARXXeOqstflqsKuXVM3H9wOIQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.48.1.tgz",
+      "integrity": "sha512-UK0WzWUjMAJccHIeOpPhPcKBqax7QFg47hwZTp6kiMhQHeOYJeaMwzeRZe1q5IiTKsaLnHu9s6toSYVUlZ2QtQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.48.1.tgz",
+      "integrity": "sha512-3NADEIlt+aCdCbWVZ7D3tBjBX1lHpXxcvrLt/kdXTiBrOds8APTdtk2yRL2GgmnSVeX4YS1JIf0imFujg78vpw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.48.1.tgz",
+      "integrity": "sha512-euuwm/QTXAMOcyiFCcrx0/S2jGvFlKJ2Iro8rsmYL53dlblp3LkUQVFzEidHhvIPPvcIsxDhl2wkBE+I6YVGzA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.48.1.tgz",
+      "integrity": "sha512-w8mULUjmPdWLJgmTYJx/W6Qhln1a+yqvgwmGXcQl2vFBkWsKGUBRbtLRuKJUln8Uaimf07zgJNxOhHOvjSQmBQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.48.1.tgz",
+      "integrity": "sha512-90taWXCWxTbClWuMZD0DKYohY1EovA+W5iytpE89oUPmT5O1HFdf8cuuVIylE6vCbrGdIGv85lVRzTcpTRZ+kA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.48.1.tgz",
+      "integrity": "sha512-2Gu29SkFh1FfTRuN1GR1afMuND2GKzlORQUP3mNMJbqdndOg7gNsa81JnORctazHRokiDzQ5+MLE5XYmZW5VWg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.48.1.tgz",
+      "integrity": "sha512-6kQFR1WuAO50bxkIlAVeIYsz3RUx+xymwhTo9j94dJ+kmHe9ly7muH23sdfWduD0BA8pD9/yhonUvAjxGh34jQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.48.1.tgz",
+      "integrity": "sha512-RUyZZ/mga88lMI3RlXFs4WQ7n3VyU07sPXmMG7/C1NOi8qisUg57Y7LRarqoGoAiopmGmChUhSwfpvQ3H5iGSQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.48.1.tgz",
+      "integrity": "sha512-8a/caCUN4vkTChxkaIJcMtwIVcBhi4X2PQRoT+yCK3qRYaZ7cURrmJFL5Ux9H9RaMIXj9RuihckdmkBX3zZsgg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@standard-schema/utils": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+      "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
+      "license": "MIT"
+    },
+    "node_modules/@tailwindcss/node": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.12.tgz",
+      "integrity": "sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/remapping": "^2.3.4",
+        "enhanced-resolve": "^5.18.3",
+        "jiti": "^2.5.1",
+        "lightningcss": "1.30.1",
+        "magic-string": "^0.30.17",
+        "source-map-js": "^1.2.1",
+        "tailwindcss": "4.1.12"
+      }
+    },
+    "node_modules/@tailwindcss/oxide": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.12.tgz",
+      "integrity": "sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "dependencies": {
+        "detect-libc": "^2.0.4",
+        "tar": "^7.4.3"
+      },
+      "engines": {
+        "node": ">= 10"
+      },
+      "optionalDependencies": {
+        "@tailwindcss/oxide-android-arm64": "4.1.12",
+        "@tailwindcss/oxide-darwin-arm64": "4.1.12",
+        "@tailwindcss/oxide-darwin-x64": "4.1.12",
+        "@tailwindcss/oxide-freebsd-x64": "4.1.12",
+        "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.12",
+        "@tailwindcss/oxide-linux-arm64-gnu": "4.1.12",
+        "@tailwindcss/oxide-linux-arm64-musl": "4.1.12",
+        "@tailwindcss/oxide-linux-x64-gnu": "4.1.12",
+        "@tailwindcss/oxide-linux-x64-musl": "4.1.12",
+        "@tailwindcss/oxide-wasm32-wasi": "4.1.12",
+        "@tailwindcss/oxide-win32-arm64-msvc": "4.1.12",
+        "@tailwindcss/oxide-win32-x64-msvc": "4.1.12"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-android-arm64": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.12.tgz",
+      "integrity": "sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-darwin-arm64": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.12.tgz",
+      "integrity": "sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-darwin-x64": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.12.tgz",
+      "integrity": "sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-freebsd-x64": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.12.tgz",
+      "integrity": "sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.12.tgz",
+      "integrity": "sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.12.tgz",
+      "integrity": "sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.12.tgz",
+      "integrity": "sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.12.tgz",
+      "integrity": "sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.12.tgz",
+      "integrity": "sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.12.tgz",
+      "integrity": "sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==",
+      "bundleDependencies": [
+        "@napi-rs/wasm-runtime",
+        "@emnapi/core",
+        "@emnapi/runtime",
+        "@tybys/wasm-util",
+        "@emnapi/wasi-threads",
+        "tslib"
+      ],
+      "cpu": [
+        "wasm32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@emnapi/core": "^1.4.5",
+        "@emnapi/runtime": "^1.4.5",
+        "@emnapi/wasi-threads": "^1.0.4",
+        "@napi-rs/wasm-runtime": "^0.2.12",
+        "@tybys/wasm-util": "^0.10.0",
+        "tslib": "^2.8.0"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.12.tgz",
+      "integrity": "sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.12.tgz",
+      "integrity": "sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/vite": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.12.tgz",
+      "integrity": "sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@tailwindcss/node": "4.1.12",
+        "@tailwindcss/oxide": "4.1.12",
+        "tailwindcss": "4.1.12"
+      },
+      "peerDependencies": {
+        "vite": "^5.2.0 || ^6 || ^7"
+      }
+    },
+    "node_modules/@types/babel__core": {
+      "version": "7.20.5",
+      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+      "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.20.7",
+        "@babel/types": "^7.20.7",
+        "@types/babel__generator": "*",
+        "@types/babel__template": "*",
+        "@types/babel__traverse": "*"
+      }
+    },
+    "node_modules/@types/babel__generator": {
+      "version": "7.27.0",
+      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+      "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__template": {
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+      "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.1.0",
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__traverse": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+      "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.28.2"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+      "license": "MIT"
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/react": {
+      "version": "19.1.11",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.11.tgz",
+      "integrity": "sha512-lr3jdBw/BGj49Eps7EvqlUaoeA0xpj3pc0RoJkHpYaCHkVK7i28dKyImLQb3JVlqs3aYSXf7qYuWOW/fgZnTXQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "csstype": "^3.0.2"
+      }
+    },
+    "node_modules/@types/react-dom": {
+      "version": "19.1.7",
+      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz",
+      "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "@types/react": "^19.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz",
+      "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/regexpp": "^4.10.0",
+        "@typescript-eslint/scope-manager": "8.40.0",
+        "@typescript-eslint/type-utils": "8.40.0",
+        "@typescript-eslint/utils": "8.40.0",
+        "@typescript-eslint/visitor-keys": "8.40.0",
+        "graphemer": "^1.4.0",
+        "ignore": "^7.0.0",
+        "natural-compare": "^1.4.0",
+        "ts-api-utils": "^2.1.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "@typescript-eslint/parser": "^8.40.0",
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+      "version": "7.0.5",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+      "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/@typescript-eslint/parser": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz",
+      "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/scope-manager": "8.40.0",
+        "@typescript-eslint/types": "8.40.0",
+        "@typescript-eslint/typescript-estree": "8.40.0",
+        "@typescript-eslint/visitor-keys": "8.40.0",
+        "debug": "^4.3.4"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/project-service": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.40.0.tgz",
+      "integrity": "sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/tsconfig-utils": "^8.40.0",
+        "@typescript-eslint/types": "^8.40.0",
+        "debug": "^4.3.4"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/scope-manager": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.40.0.tgz",
+      "integrity": "sha512-y9ObStCcdCiZKzwqsE8CcpyuVMwRouJbbSrNuThDpv16dFAj429IkM6LNb1dZ2m7hK5fHyzNcErZf7CEeKXR4w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/types": "8.40.0",
+        "@typescript-eslint/visitor-keys": "8.40.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/tsconfig-utils": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.40.0.tgz",
+      "integrity": "sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz",
+      "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/types": "8.40.0",
+        "@typescript-eslint/typescript-estree": "8.40.0",
+        "@typescript-eslint/utils": "8.40.0",
+        "debug": "^4.3.4",
+        "ts-api-utils": "^2.1.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/types": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.40.0.tgz",
+      "integrity": "sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.40.0.tgz",
+      "integrity": "sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/project-service": "8.40.0",
+        "@typescript-eslint/tsconfig-utils": "8.40.0",
+        "@typescript-eslint/types": "8.40.0",
+        "@typescript-eslint/visitor-keys": "8.40.0",
+        "debug": "^4.3.4",
+        "fast-glob": "^3.3.2",
+        "is-glob": "^4.0.3",
+        "minimatch": "^9.0.4",
+        "semver": "^7.6.0",
+        "ts-api-utils": "^2.1.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+      "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@typescript-eslint/utils": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.40.0.tgz",
+      "integrity": "sha512-Cgzi2MXSZyAUOY+BFwGs17s7ad/7L+gKt6Y8rAVVWS+7o6wrjeFN4nVfTpbE25MNcxyJ+iYUXflbs2xR9h4UBg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.7.0",
+        "@typescript-eslint/scope-manager": "8.40.0",
+        "@typescript-eslint/types": "8.40.0",
+        "@typescript-eslint/typescript-estree": "8.40.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/visitor-keys": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.40.0.tgz",
+      "integrity": "sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/types": "8.40.0",
+        "eslint-visitor-keys": "^4.2.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@vitejs/plugin-react": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.1.tgz",
+      "integrity": "sha512-DE4UNaBXwtVoDJ0ccBdLVjFTWL70NRuWNCxEieTI3lrq9ORB9aOCQEKstwDXBl87NvFdbqh/p7eINGyj0BthJA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/core": "^7.28.3",
+        "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+        "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+        "@rolldown/pluginutils": "1.0.0-beta.32",
+        "@types/babel__core": "^7.20.5",
+        "react-refresh": "^0.17.0"
+      },
+      "engines": {
+        "node": "^20.19.0 || >=22.12.0"
+      },
+      "peerDependencies": {
+        "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.15.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+      "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-jsx": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true,
+      "license": "Python-2.0"
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
+    "node_modules/axios": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
+      "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.4",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.12",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+      "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "fill-range": "^7.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.25.3",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz",
+      "integrity": "sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001735",
+        "electron-to-chromium": "^1.5.204",
+        "node-releases": "^2.0.19",
+        "update-browserslist-db": "^1.1.3"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001737",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz",
+      "integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "CC-BY-4.0"
+    },
+    "node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/chownr": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+      "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/cookie": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+      "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+      "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deep-is": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
+      "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.5.208",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.208.tgz",
+      "integrity": "sha512-ozZyibehoe7tOhNaf16lKmljVf+3npZcJIEbJRVftVsmAg5TeA1mGS9dVCZzOwr2xT7xK15V0p7+GZqSPgkuPg==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/enhanced-resolve": {
+      "version": "5.18.3",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
+      "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
+      "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.25.9",
+        "@esbuild/android-arm": "0.25.9",
+        "@esbuild/android-arm64": "0.25.9",
+        "@esbuild/android-x64": "0.25.9",
+        "@esbuild/darwin-arm64": "0.25.9",
+        "@esbuild/darwin-x64": "0.25.9",
+        "@esbuild/freebsd-arm64": "0.25.9",
+        "@esbuild/freebsd-x64": "0.25.9",
+        "@esbuild/linux-arm": "0.25.9",
+        "@esbuild/linux-arm64": "0.25.9",
+        "@esbuild/linux-ia32": "0.25.9",
+        "@esbuild/linux-loong64": "0.25.9",
+        "@esbuild/linux-mips64el": "0.25.9",
+        "@esbuild/linux-ppc64": "0.25.9",
+        "@esbuild/linux-riscv64": "0.25.9",
+        "@esbuild/linux-s390x": "0.25.9",
+        "@esbuild/linux-x64": "0.25.9",
+        "@esbuild/netbsd-arm64": "0.25.9",
+        "@esbuild/netbsd-x64": "0.25.9",
+        "@esbuild/openbsd-arm64": "0.25.9",
+        "@esbuild/openbsd-x64": "0.25.9",
+        "@esbuild/openharmony-arm64": "0.25.9",
+        "@esbuild/sunos-x64": "0.25.9",
+        "@esbuild/win32-arm64": "0.25.9",
+        "@esbuild/win32-ia32": "0.25.9",
+        "@esbuild/win32-x64": "0.25.9"
+      }
+    },
+    "node_modules/escalade": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint": {
+      "version": "9.34.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz",
+      "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/regexpp": "^4.12.1",
+        "@eslint/config-array": "^0.21.0",
+        "@eslint/config-helpers": "^0.3.1",
+        "@eslint/core": "^0.15.2",
+        "@eslint/eslintrc": "^3.3.1",
+        "@eslint/js": "9.34.0",
+        "@eslint/plugin-kit": "^0.3.5",
+        "@humanfs/node": "^0.16.6",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@humanwhocodes/retry": "^0.4.2",
+        "@types/estree": "^1.0.6",
+        "@types/json-schema": "^7.0.15",
+        "ajv": "^6.12.4",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.6",
+        "debug": "^4.3.2",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^8.4.0",
+        "eslint-visitor-keys": "^4.2.1",
+        "espree": "^10.4.0",
+        "esquery": "^1.5.0",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^8.0.0",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://eslint.org/donate"
+      },
+      "peerDependencies": {
+        "jiti": "*"
+      },
+      "peerDependenciesMeta": {
+        "jiti": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint-plugin-react-hooks": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+      "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+      }
+    },
+    "node_modules/eslint-plugin-react-refresh": {
+      "version": "0.4.20",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz",
+      "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "eslint": ">=8.40"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "8.4.0",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+      "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-visitor-keys": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+      "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/espree": {
+      "version": "10.4.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+      "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "acorn": "^8.15.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^4.2.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esquery": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+      "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "estraverse": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fast-glob": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+      "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.8"
+      },
+      "engines": {
+        "node": ">=8.6.0"
+      }
+    },
+    "node_modules/fast-glob/node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fastq": {
+      "version": "1.19.1",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+      "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "node_modules/file-entry-cache": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+      "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "flat-cache": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/flat-cache": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+      "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "flatted": "^3.2.9",
+        "keyv": "^4.5.4"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/flatted": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+      "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.15.11",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+      "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
+      "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "license": "MIT",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/globals": {
+      "version": "16.3.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz",
+      "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "license": "ISC"
+    },
+    "node_modules/graphemer": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+      "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/ignore": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+      "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/import-fresh": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+      "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/jiti": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
+      "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==",
+      "license": "MIT",
+      "bin": {
+        "jiti": "lib/jiti-cli.mjs"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/json-buffer": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/keyv": {
+      "version": "4.5.4",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+      "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "json-buffer": "3.0.1"
+      }
+    },
+    "node_modules/levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/lightningcss": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
+      "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
+      "license": "MPL-2.0",
+      "dependencies": {
+        "detect-libc": "^2.0.3"
+      },
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      },
+      "optionalDependencies": {
+        "lightningcss-darwin-arm64": "1.30.1",
+        "lightningcss-darwin-x64": "1.30.1",
+        "lightningcss-freebsd-x64": "1.30.1",
+        "lightningcss-linux-arm-gnueabihf": "1.30.1",
+        "lightningcss-linux-arm64-gnu": "1.30.1",
+        "lightningcss-linux-arm64-musl": "1.30.1",
+        "lightningcss-linux-x64-gnu": "1.30.1",
+        "lightningcss-linux-x64-musl": "1.30.1",
+        "lightningcss-win32-arm64-msvc": "1.30.1",
+        "lightningcss-win32-x64-msvc": "1.30.1"
+      }
+    },
+    "node_modules/lightningcss-darwin-arm64": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz",
+      "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-darwin-x64": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz",
+      "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-freebsd-x64": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz",
+      "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-arm-gnueabihf": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz",
+      "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-arm64-gnu": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz",
+      "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-arm64-musl": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz",
+      "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-x64-gnu": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
+      "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-linux-x64-musl": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz",
+      "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-win32-arm64-msvc": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz",
+      "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/lightningcss-win32-x64-msvc": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz",
+      "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MPL-2.0",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.18",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz",
+      "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minipass": {
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+      "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      }
+    },
+    "node_modules/minizlib": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
+      "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
+      "license": "MIT",
+      "dependencies": {
+        "minipass": "^7.1.2"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/mkdirp": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+      "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
+      "license": "MIT",
+      "bin": {
+        "mkdirp": "dist/cjs/src/bin.js"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.19",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+      "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/optionator": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+      "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0",
+        "word-wrap": "^1.2.5"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.6",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+      "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/prelude-ls": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+      "license": "MIT"
+    },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/react": {
+      "version": "19.1.1",
+      "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
+      "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-dom": {
+      "version": "19.1.1",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
+      "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
+      "license": "MIT",
+      "dependencies": {
+        "scheduler": "^0.26.0"
+      },
+      "peerDependencies": {
+        "react": "^19.1.1"
+      }
+    },
+    "node_modules/react-hook-form": {
+      "version": "7.62.0",
+      "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.62.0.tgz",
+      "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/react-hook-form"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17 || ^18 || ^19"
+      }
+    },
+    "node_modules/react-refresh": {
+      "version": "0.17.0",
+      "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+      "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-router": {
+      "version": "7.8.2",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.2.tgz",
+      "integrity": "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ==",
+      "license": "MIT",
+      "dependencies": {
+        "cookie": "^1.0.1",
+        "set-cookie-parser": "^2.6.0"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=18",
+        "react-dom": ">=18"
+      },
+      "peerDependenciesMeta": {
+        "react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/react-router-dom": {
+      "version": "7.8.2",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.8.2.tgz",
+      "integrity": "sha512-Z4VM5mKDipal2jQ385H6UBhiiEDlnJPx6jyWsTYoZQdl5TrjxEV2a9yl3Fi60NBJxYzOTGTTHXPi0pdizvTwow==",
+      "license": "MIT",
+      "dependencies": {
+        "react-router": "7.8.2"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=18",
+        "react-dom": ">=18"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/reusify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+      "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "4.48.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.48.1.tgz",
+      "integrity": "sha512-jVG20NvbhTYDkGAty2/Yh7HK6/q3DGSRH4o8ALKGArmMuaauM9kLfoMZ+WliPwA5+JHr2lTn3g557FxBV87ifg==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "1.0.8"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.48.1",
+        "@rollup/rollup-android-arm64": "4.48.1",
+        "@rollup/rollup-darwin-arm64": "4.48.1",
+        "@rollup/rollup-darwin-x64": "4.48.1",
+        "@rollup/rollup-freebsd-arm64": "4.48.1",
+        "@rollup/rollup-freebsd-x64": "4.48.1",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.48.1",
+        "@rollup/rollup-linux-arm-musleabihf": "4.48.1",
+        "@rollup/rollup-linux-arm64-gnu": "4.48.1",
+        "@rollup/rollup-linux-arm64-musl": "4.48.1",
+        "@rollup/rollup-linux-loongarch64-gnu": "4.48.1",
+        "@rollup/rollup-linux-ppc64-gnu": "4.48.1",
+        "@rollup/rollup-linux-riscv64-gnu": "4.48.1",
+        "@rollup/rollup-linux-riscv64-musl": "4.48.1",
+        "@rollup/rollup-linux-s390x-gnu": "4.48.1",
+        "@rollup/rollup-linux-x64-gnu": "4.48.1",
+        "@rollup/rollup-linux-x64-musl": "4.48.1",
+        "@rollup/rollup-win32-arm64-msvc": "4.48.1",
+        "@rollup/rollup-win32-ia32-msvc": "4.48.1",
+        "@rollup/rollup-win32-x64-msvc": "4.48.1",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "node_modules/scheduler": {
+      "version": "0.26.0",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+      "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
+      "license": "MIT"
+    },
+    "node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/set-cookie-parser": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+      "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+      "license": "MIT"
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tailwindcss": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz",
+      "integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==",
+      "license": "MIT"
+    },
+    "node_modules/tapable": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz",
+      "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/tar": {
+      "version": "7.4.3",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
+      "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
+      "license": "ISC",
+      "dependencies": {
+        "@isaacs/fs-minipass": "^4.0.0",
+        "chownr": "^3.0.0",
+        "minipass": "^7.1.2",
+        "minizlib": "^3.0.1",
+        "mkdirp": "^3.0.1",
+        "yallist": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/tar/node_modules/yallist": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+      "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/tinyglobby": {
+      "version": "0.2.14",
+      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
+      "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+      "license": "MIT",
+      "dependencies": {
+        "fdir": "^6.4.4",
+        "picomatch": "^4.0.2"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/SuperchupuDev"
+      }
+    },
+    "node_modules/tinyglobby/node_modules/fdir": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tinyglobby/node_modules/picomatch": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+      "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/ts-api-utils": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+      "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.12"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4"
+      }
+    },
+    "node_modules/type-check": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/typescript-eslint": {
+      "version": "8.40.0",
+      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.40.0.tgz",
+      "integrity": "sha512-Xvd2l+ZmFDPEt4oj1QEXzA4A2uUK6opvKu3eGN9aGjB8au02lIVcLyi375w94hHyejTOmzIU77L8ol2sRg9n7Q==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/eslint-plugin": "8.40.0",
+        "@typescript-eslint/parser": "8.40.0",
+        "@typescript-eslint/typescript-estree": "8.40.0",
+        "@typescript-eslint/utils": "8.40.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+      "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "escalade": "^3.2.0",
+        "picocolors": "^1.1.1"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/vite": {
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz",
+      "integrity": "sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==",
+      "license": "MIT",
+      "dependencies": {
+        "esbuild": "^0.25.0",
+        "fdir": "^6.5.0",
+        "picomatch": "^4.0.3",
+        "postcss": "^8.5.6",
+        "rollup": "^4.43.0",
+        "tinyglobby": "^0.2.14"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^20.19.0 || >=22.12.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^20.19.0 || >=22.12.0",
+        "jiti": ">=1.21.0",
+        "less": "^4.0.0",
+        "lightningcss": "^1.21.0",
+        "sass": "^1.70.0",
+        "sass-embedded": "^1.70.0",
+        "stylus": ">=0.54.8",
+        "sugarss": "^5.0.0",
+        "terser": "^5.16.0",
+        "tsx": "^4.8.1",
+        "yaml": "^2.4.2"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "jiti": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        },
+        "tsx": {
+          "optional": true
+        },
+        "yaml": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vite/node_modules/fdir": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vite/node_modules/picomatch": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+      "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/word-wrap": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+      "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/zod": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.1.tgz",
+      "integrity": "sha512-SgMZK/h8Tigt9nnKkfJMvB/mKjiJXaX26xegP4sa+0wHIFVFWVlsQGdhklDmuargBD3Hsi3rsQRIzwJIhTPJHA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/colinhacks"
+      }
+    }
+  }
+}
Index: frontend/package.json
===================================================================
--- frontend/package.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/package.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,36 @@
+{
+  "name": "tasty-tabs-admin",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "tsc -b && vite build",
+    "lint": "eslint .",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@hookform/resolvers": "^5.2.1",
+    "@tailwindcss/vite": "^4.1.12",
+    "axios": "^1.11.0",
+    "react": "^19.1.1",
+    "react-dom": "^19.1.1",
+    "react-hook-form": "^7.62.0",
+    "react-router-dom": "^7.8.2",
+    "tailwindcss": "^4.1.12",
+    "zod": "^4.1.1"
+  },
+  "devDependencies": {
+    "@eslint/js": "^9.33.0",
+    "@types/react": "^19.1.10",
+    "@types/react-dom": "^19.1.7",
+    "@vitejs/plugin-react": "^5.0.0",
+    "eslint": "^9.33.0",
+    "eslint-plugin-react-hooks": "^5.2.0",
+    "eslint-plugin-react-refresh": "^0.4.20",
+    "globals": "^16.3.0",
+    "typescript": "~5.8.3",
+    "typescript-eslint": "^8.39.1",
+    "vite": "^7.1.2"
+  }
+}
Index: frontend/public/vite.svg
===================================================================
--- frontend/public/vite.svg	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/public/vite.svg	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
Index: frontend/src/App.tsx
===================================================================
--- frontend/src/App.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/App.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,91 @@
+// src/App.tsx
+import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';
+import { AuthProvider } from './context/AuthContext';
+import { ROLES } from './utils/roles';
+
+// Layouts
+import { Navbar as AdminNavbar } from './components/Navbar';
+import { PublicNavbar } from './components/public/PublicNavbar';
+
+// Common Pages
+import { LoginPage } from './pages/LoginPage';
+import { ProtectedRoute } from './components/ProtectedRoute';
+
+// Admin Pages
+import DashboardPage from './pages/DashboardPage';
+import { OrdersPage } from './pages/OrdersPage';
+import { OrderDetailsPage } from './pages/OrderDetailsPage';
+import { ReservationsPage as AdminReservationsPage } from './pages/ReservationsPage';
+import { CategoriesPage } from './pages/CategoriesPage';
+import { ProductsPage } from './pages/ProductsPage';
+import { ShiftsPage } from './pages/ShiftsPage';
+import { EmployeesPage } from './pages/EmployeesPage';
+import { AssignmentsPage } from './pages/AssignmentsPage';
+
+// Public Pages
+import { RegisterPage } from './pages/public/RegisterPage';
+import { MenuPage } from './pages/public/MenuPage';
+import { MyReservationsPage } from './pages/public/MyReservationsPage';
+import { MyOrdersPage } from './pages/public/MyOrdersPage';
+
+// Admin Layout
+const AdminLayout = () => (
+    <div className="bg-gray-50 min-h-screen">
+        <AdminNavbar />
+        <main><Outlet /></main>
+    </div>
+);
+
+// Public Layout
+const PublicLayout = () => (
+    <div>
+        <PublicNavbar />
+        <main><Outlet /></main>
+    </div>
+);
+
+function App() {
+    return (
+        <AuthProvider>
+            <BrowserRouter>
+                <Routes>
+                    {/* Public Routes */}
+                    <Route element={<PublicLayout />}>
+                        <Route path="/" element={<MenuPage />} />
+                        <Route path="/login" element={<LoginPage />} />
+                        <Route path="/register" element={<RegisterPage />} />
+                        <Route path="/my-orders" element={<ProtectedRoute allowedRoles={[ROLES.CUSTOMER, ROLES.MANAGER, ROLES.USER]} />}>
+                            <Route index element={<MyOrdersPage />} />
+                        </Route>
+                        <Route path="/my-reservations" element={<ProtectedRoute allowedRoles={[ROLES.CUSTOMER, ROLES.MANAGER, ROLES.USER]} />}>
+                            <Route index element={<MyReservationsPage />} />
+                        </Route>
+                    </Route>
+
+                    {/* Admin Routes */}
+                    <Route path="/admin" element={<AdminLayout />}>
+                        <Route path="" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER, ROLES.FRONT_STAFF, ROLES.BACK_STAFF]} />}>
+                            <Route index element={<DashboardPage />} />
+                        </Route>
+                        <Route path="orders" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER, ROLES.FRONT_STAFF, ROLES.BACK_STAFF]} />}>
+                            <Route index element={<OrdersPage />} />
+                            <Route path=":orderId" element={<OrderDetailsPage />} />
+                        </Route>
+                        <Route path="reservations" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER, ROLES.FRONT_STAFF]} />}>
+                            <Route index element={<AdminReservationsPage />} />
+                        </Route>
+                        <Route path="categories" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER]} />}><Route index element={<CategoriesPage />} /></Route>
+                        <Route path="products" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER]} />}><Route index element={<ProductsPage />} /></Route>
+                        <Route path="shifts" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER]} />}><Route index element={<ShiftsPage />} /></Route>
+                        <Route path="employees" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER]} />}><Route index element={<EmployeesPage />} /></Route>
+                        <Route path="assignments" element={<ProtectedRoute allowedRoles={[ROLES.MANAGER]} />}><Route index element={<AssignmentsPage />} /></Route>
+                    </Route>
+
+                    <Route path="*" element={<div>404 Not Found</div>} />
+                </Routes>
+            </BrowserRouter>
+        </AuthProvider>
+    );
+}
+
+export default App;
Index: frontend/src/api/assignmentRepository.ts
===================================================================
--- frontend/src/api/assignmentRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/assignmentRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,37 @@
+// src/api/assignmentRepository.ts
+import axiosClient from "./axiosClient";
+import type { AssignmentDto, CreateAssignmentDto } from "../types/api";
+
+export const assignmentRepository = {
+  getAllAssignments: async (): Promise<AssignmentDto[]> => {
+    const { data } = await axiosClient.get("/assignments");
+    return data;
+  },
+  createAssignment: async (
+    assignmentData: CreateAssignmentDto,
+  ): Promise<AssignmentDto> => {
+    const { data } = await axiosClient.post("/assignments", assignmentData);
+    return data;
+  },
+  // New method to get an employee's next shift
+  getNextShift: async (employeeId: number): Promise<AssignmentDto> => {
+    const { data } = await axiosClient.get(
+      `/employees/${employeeId}/shifts/next`,
+    );
+    return data;
+  },
+  // New method for clocking in
+  clockIn: async (assignmentId: number): Promise<AssignmentDto> => {
+    const { data } = await axiosClient.post(
+      `/assignments/${assignmentId}/clockin`,
+    );
+    return data;
+  },
+  // New method for clocking out
+  clockOut: async (assignmentId: number): Promise<AssignmentDto> => {
+    const { data } = await axiosClient.post(
+      `/assignments/${assignmentId}/clockout`,
+    );
+    return data;
+  },
+};
Index: frontend/src/api/authRepository.ts
===================================================================
--- frontend/src/api/authRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/authRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,15 @@
+// src/api/authRepository.ts
+import axiosClient from "./axiosClient";
+import type { AuthRequest, AuthDto, RegisterRequest } from "../types/api";
+
+export const authRepository = {
+  login: async (credentials: AuthRequest): Promise<AuthDto> => {
+    const { data } = await axiosClient.post("/auth/login", credentials);
+    return data;
+  },
+  // New method for customer registration
+  register: async (registerData: RegisterRequest): Promise<AuthDto> => {
+    const { data } = await axiosClient.post("/auth/register", registerData);
+    return data;
+  },
+};
Index: frontend/src/api/axiosClient.ts
===================================================================
--- frontend/src/api/axiosClient.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/axiosClient.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,25 @@
+// src/api/axiosClient.ts
+import axios from "axios";
+
+const axiosClient = axios.create({
+  baseURL: "http://localhost:8080/api", // Your backend URL
+  headers: {
+    "Content-Type": "application/json",
+  },
+});
+
+// Interceptor to add the auth token to every request
+axiosClient.interceptors.request.use(
+  (config) => {
+    const token = localStorage.getItem("authToken");
+    if (token) {
+      config.headers.Authorization = `Bearer ${token}`;
+    }
+    return config;
+  },
+  (error) => {
+    return Promise.reject(error);
+  },
+);
+
+export default axiosClient;
Index: frontend/src/api/categoryRepository.ts
===================================================================
--- frontend/src/api/categoryRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/categoryRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,19 @@
+// src/api/categoryRepository.ts
+import axiosClient from "./axiosClient";
+import type { CategoryDto, CreateCategoryDto } from "../types/api";
+
+export const categoryRepository = {
+  getAllCategories: async (): Promise<CategoryDto[]> => {
+    const { data } = await axiosClient.get("/categories");
+    return data;
+  },
+  createCategory: async (
+    categoryData: CreateCategoryDto,
+  ): Promise<CategoryDto> => {
+    const { data } = await axiosClient.post("/categories/add", categoryData);
+    return data;
+  },
+  deleteCategory: async (categoryId: number): Promise<void> => {
+    await axiosClient.delete(`/categories/delete/${categoryId}`);
+  },
+};
Index: frontend/src/api/employeeRepository.ts
===================================================================
--- frontend/src/api/employeeRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/employeeRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,20 @@
+// src/api/employeeRepository.ts
+import axiosClient from "./axiosClient";
+import type { EmployeeDto, CreateEmployeeRequest } from "../types/api";
+
+export const employeeRepository = {
+  // As per your instruction, the endpoint is /employees
+  getAllEmployees: async (): Promise<EmployeeDto[]> => {
+    const { data } = await axiosClient.get("/employees");
+    return data;
+  },
+  createEmployee: async (
+    employeeData: CreateEmployeeRequest,
+  ): Promise<EmployeeDto> => {
+    const { data } = await axiosClient.post(
+      "/employees/manager/create",
+      employeeData,
+    );
+    return data;
+  },
+};
Index: frontend/src/api/orderRepository.ts
===================================================================
--- frontend/src/api/orderRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/orderRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,79 @@
+// src/api/orderRepository.ts
+import axiosClient from "./axiosClient";
+// Add CreateOrderItemDto to imports
+import type {
+  OrderDto,
+  CreateOrderDto,
+  CreateOrderItemDto,
+  OrderItemDto,
+} from "../types/api";
+
+// Helper to convert existing order items to the format needed for the update payload
+const mapOrderItemsToCreateDto = (
+  items: OrderItemDto[],
+): CreateOrderItemDto[] => {
+  return items.map((item) => ({
+    product_id: item.product_id,
+    quantity: item.quantity,
+    price: item.price,
+    is_processed: item.is_processed,
+  }));
+};
+
+export const orderRepository = {
+  getOpenOrders: async (): Promise<OrderDto[]> => {
+    const { data } = await axiosClient.get("/orders/open");
+    return data;
+  },
+  createOnlineOrder: async (orderData: CreateOrderDto): Promise<OrderDto> => {
+    const { data } = await axiosClient.post("/orders/online", orderData);
+    return data;
+  },
+  getOnlineOrdersByCustomer: async (
+    customerId: number,
+  ): Promise<OrderDto[]> => {
+    const { data } = await axiosClient.get(
+      `/orders/online/customer/${customerId}`,
+    );
+    return data;
+  },
+  // New method to get a single order
+  getOrderById: async (orderId: number): Promise<OrderDto> => {
+    const { data } = await axiosClient.get(`/orders/${orderId}`);
+    return data;
+  },
+  createTabOrder: async (orderData: CreateOrderDto): Promise<OrderDto> => {
+    const { data } = await axiosClient.post("/orders/tab", orderData);
+    return data;
+  },
+  // New method to add items to an existing order
+  addItemToOrder: async (
+    orderId: number,
+    itemData: CreateOrderItemDto,
+  ): Promise<void> => {
+    // Note: The API docs show adding one item at a time.
+    // If you could add multiple, the payload would be CreateOrderItemDto[]
+    await axiosClient.post(`/orders/${orderId}/items`, itemData);
+  },
+
+  updateOrderStatus: async (orderId: number, status: string): Promise<void> => {
+    // The endpoint expects a raw string, not a JSON object
+    await axiosClient.patch(`/orders/${orderId}/status`, { status });
+  },
+
+  // New method to handle general updates
+  updateOrder: async (order: OrderDto): Promise<OrderDto> => {
+    const updatePayload: CreateOrderDto = {
+      status: order.status,
+      type: order.type,
+      table_number: order.table_number,
+      delivery_address: order.delivery_address,
+      order_items: mapOrderItemsToCreateDto(order.order_items),
+    };
+    const { data } = await axiosClient.put(
+      `/orders/${order.id}`,
+      updatePayload,
+    );
+    return data;
+  },
+};
Index: frontend/src/api/productRepository.ts
===================================================================
--- frontend/src/api/productRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/productRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,17 @@
+// src/api/productRepository.ts
+import axiosClient from "./axiosClient";
+import type { ProductDto, CreateProductDto } from "../types/api";
+
+export const productRepository = {
+  getAllProducts: async (): Promise<ProductDto[]> => {
+    const { data } = await axiosClient.get("/products");
+    return data;
+  },
+  createProduct: async (productData: CreateProductDto): Promise<ProductDto> => {
+    const { data } = await axiosClient.post("/products/add", productData);
+    return data;
+  },
+  deleteProduct: async (productId: number): Promise<void> => {
+    await axiosClient.delete(`/products/delete/${productId}`);
+  },
+};
Index: frontend/src/api/reservationRepository.ts
===================================================================
--- frontend/src/api/reservationRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/reservationRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,39 @@
+// src/api/reservationRepository.ts
+import axiosClient from "./axiosClient";
+// Make sure CreateReservationDto is imported
+import type { ReservationDto, CreateReservationDto } from "../types/api";
+
+export const reservationRepository = {
+  getTodayReservations: async (): Promise<ReservationDto[]> => {
+    const { data } = await axiosClient.get("/reservations/today");
+    return data;
+  },
+  acceptReservation: async (
+    reservationId: number,
+    tableNumber: number,
+  ): Promise<ReservationDto> => {
+    const { data } = await axiosClient.post(
+      `/reservations/accept/${reservationId}/table/${tableNumber}`,
+    );
+    return data;
+  },
+  // Add this new method
+  createReservation: async (
+    reservationData: CreateReservationDto,
+  ): Promise<ReservationDto> => {
+    const { data } = await axiosClient.post(
+      "/reservations/add",
+      reservationData,
+    );
+    return data;
+  },
+
+  getMyReservations: async (): Promise<ReservationDto[]> => {
+    const { data } = await axiosClient.get("/reservations/myReservations");
+    return data;
+  },
+  // New method to delete/cancel a reservation
+  deleteReservation: async (reservationId: number): Promise<void> => {
+    await axiosClient.delete(`/reservations/delete/${reservationId}`);
+  },
+};
Index: frontend/src/api/shiftRepository.ts
===================================================================
--- frontend/src/api/shiftRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/api/shiftRepository.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,14 @@
+// src/api/shiftRepository.ts
+import axiosClient from "./axiosClient";
+import type { ShiftDto, CreateShiftDto } from "../types/api";
+
+export const shiftRepository = {
+  getAllShifts: async (): Promise<ShiftDto[]> => {
+    const { data } = await axiosClient.get("/shifts");
+    return data;
+  },
+  createShift: async (shiftData: CreateShiftDto): Promise<ShiftDto> => {
+    const { data } = await axiosClient.post("/shifts", shiftData);
+    return data;
+  },
+};
Index: frontend/src/assets/react.svg
===================================================================
--- frontend/src/assets/react.svg	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/assets/react.svg	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
Index: frontend/src/components/AddItemModal.tsx
===================================================================
--- frontend/src/components/AddItemModal.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/AddItemModal.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,144 @@
+// src/components/modals/AddItemModal.tsx
+import { useEffect, useState } from 'react';
+import type { CategoryDto, ProductDto, CreateOrderItemDto } from '../types/api';
+import { categoryRepository } from '../api/categoryRepository';
+import { productRepository } from '../api/productRepository';
+import { orderRepository } from '../api/orderRepository';
+import { Modal } from './Modal';
+
+interface CartItem extends ProductDto {
+    quantity: number;
+}
+
+interface AddItemModalProps {
+    isOpen: boolean;
+    onClose: () => void;
+    orderId: number;
+    onSuccess: () => void; // To refresh the order details page
+}
+
+export const AddItemModal = ({ isOpen, onClose, orderId, onSuccess }: AddItemModalProps) => {
+    const [view, setView] = useState<'categories' | 'products'>('categories');
+    const [categories, setCategories] = useState<CategoryDto[]>([]);
+    const [products, setProducts] = useState<ProductDto[]>([]);
+    const [selectedCategory, setSelectedCategory] = useState<CategoryDto | null>(null);
+    const [cart, setCart] = useState<Record<number, CartItem>>({});
+    const [isSubmitting, setIsSubmitting] = useState(false);
+
+    useEffect(() => {
+        if (isOpen) {
+            // Reset state when modal opens
+            setView('categories');
+            setCart({});
+            categoryRepository.getAllCategories().then(setCategories).catch(console.error);
+        }
+    }, [isOpen]);
+
+    const handleCategorySelect = (category: CategoryDto) => {
+        setSelectedCategory(category);
+        // You might need a productRepository.getProductsByCategoryId(category.id) method here.
+        // For now, we'll filter the full product list.
+        productRepository.getAllProducts().then(allProducts => {
+            const filteredProducts = allProducts.filter(p => p.category.id === category.id);
+            setProducts(filteredProducts);
+            setView('products');
+        }).catch(console.error);
+    };
+
+    const updateCart = (product: ProductDto, change: 1 | -1) => {
+        setCart(prevCart => {
+            const existingItem = prevCart[product.id];
+            const newQuantity = (existingItem?.quantity || 0) + change;
+
+            if (newQuantity <= 0) {
+                const { [product.id]: _, ...rest } = prevCart;
+                return rest;
+            }
+
+            return {
+                ...prevCart,
+                [product.id]: { ...product, quantity: newQuantity },
+            };
+        });
+    };
+
+    const handleBackToCategories = () => {
+        setView('categories');
+        setSelectedCategory(null);
+    };
+
+    const handleSubmitItems = async () => {
+        setIsSubmitting(true);
+        try {
+            const itemsToAdd: CreateOrderItemDto[] = Object.values(cart).map(item => ({
+                product_id: item.id,
+                quantity: item.quantity,
+                price: item.price, // Price might be determined by the backend
+                is_processed: false,
+            }));
+
+            // The API adds one item at a time, so we must loop.
+            // A batch endpoint would be more efficient here.
+            for (const item of itemsToAdd) {
+                await orderRepository.addItemToOrder(orderId, item);
+            }
+
+            onSuccess();
+            onClose();
+        } catch (error) {
+            console.error("Failed to add items:", error);
+            alert("An error occurred while adding items.");
+        } finally {
+            setIsSubmitting(false);
+        }
+    };
+
+    const cartTotal = Object.values(cart).reduce((sum, item) => sum + item.price * item.quantity, 0);
+
+    return (
+        <Modal isOpen={isOpen} onClose={onClose} title={view === 'categories' ? 'Select a Category' : `Products in ${selectedCategory?.name}`}>
+            <div className="min-h-[400px]">
+                {view === 'products' && (
+                    <button onClick={handleBackToCategories} className="mb-4 text-sm text-blue-600 hover:underline">&larr; Back to Categories</button>
+                )}
+
+                {view === 'categories' && (
+                    <div className="grid grid-cols-2 md:grid-cols-3 gap-4">
+                        {categories.filter(c => c.is_available).map(cat => (
+                            <button key={cat.id} onClick={() => handleCategorySelect(cat)} className="p-4 bg-gray-100 hover:bg-blue-100 rounded-lg text-center font-semibold">
+                                {cat.name}
+                            </button>
+                        ))}
+                    </div>
+                )}
+
+                {view === 'products' && (
+                    <div className="space-y-3">
+                        {products.map(prod => (
+                            <div key={prod.id} className="flex justify-between items-center p-2 border rounded-lg">
+                                <div>
+                                    <p className="font-semibold">{prod.name}</p>
+                                    <p className="text-sm text-gray-600">${prod.price.toFixed(2)}</p>
+                                </div>
+                                <div className="flex items-center space-x-3">
+                                    <button onClick={() => updateCart(prod, -1)} className="bg-red-500 text-white rounded-full w-6 h-6 flex items-center justify-center font-bold">-</button>
+                                    <span>{cart[prod.id]?.quantity || 0}</span>
+                                    <button onClick={() => updateCart(prod, 1)} className="bg-green-500 text-white rounded-full w-6 h-6 flex items-center justify-center font-bold">+</button>
+                                </div>
+                            </div>
+                        ))}
+                    </div>
+                )}
+            </div>
+
+            {Object.keys(cart).length > 0 && (
+                <div className="mt-4 pt-4 border-t flex justify-between items-center">
+                    <p className="font-semibold">Total: ${cartTotal.toFixed(2)}</p>
+                    <button onClick={handleSubmitItems} disabled={isSubmitting} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+                        {isSubmitting ? 'Adding...' : `Add ${Object.values(cart).reduce((sum, item) => sum + item.quantity, 0)} Items`}
+                    </button>
+                </div>
+            )}
+        </Modal>
+    );
+};
Index: frontend/src/components/Modal.tsx
===================================================================
--- frontend/src/components/Modal.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/Modal.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,26 @@
+// src/components/Modal.tsx
+import { type ReactNode } from 'react';
+
+interface ModalProps {
+    isOpen: boolean;
+    onClose: () => void;
+    title: string;
+    children: ReactNode;
+}
+
+export const Modal = ({ isOpen, onClose, title, children }: ModalProps) => {
+    if (!isOpen) return null;
+
+    return (
+        <div className="fixed inset-0 bg-opacity-50 z-50 flex justify-center items-center">
+            <div className="fixed inset-0 bg-black opacity-50" onClick={onClose}></div>
+            <div className="bg-white rounded-lg shadow-xl p-6 w-full max-w-lg relative">
+                <div className="flex justify-between items-center border-b pb-3 mb-4">
+                    <h3 className="text-xl font-semibold">{title}</h3>
+                    <button onClick={onClose} className="text-black close-modal text-2xl font-bold">&times;</button>
+                </div>
+                <div>{children}</div>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/components/Navbar.tsx
===================================================================
--- frontend/src/components/Navbar.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/Navbar.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,66 @@
+// src/components/Navbar.tsx
+import { NavLink, useNavigate } from 'react-router-dom';
+import { useAuth } from '../hooks/useAuth';
+import { ROLE_PERMISSIONS } from '../utils/roles';
+
+const navLinks = [
+    { path: '/admin/orders', label: 'Orders' },
+    { path: '/admin/reservations', label: 'Reservations' },
+    { path: '/admin/categories', label: 'Categories' }, // New
+    { path: '/admin/products', label: 'Products' }, // New
+    { path: '/admin/shifts', label: 'Shifts' },
+    { path: '/admin/employees', label: 'Employees' },
+    { path: '/admin/assignments', label: 'Assignments' },
+];
+
+
+export const Navbar = () => {
+    const { isAuthenticated, logout, user } = useAuth();
+    const navigate = useNavigate();
+
+    const handleLogout = () => {
+        logout();
+        navigate('/login');
+    };
+
+    const availableLinks = isAuthenticated && user
+        ? navLinks.filter(link => ROLE_PERMISSIONS[user.user_type]?.includes(link.path))
+        : [];
+
+    return (
+        <nav className="bg-gray-800 text-white p-4 flex justify-between items-center">
+            <div className="flex items-center space-x-6">
+                <NavLink to="/" className="text-xl font-bold">TastyTabs</NavLink>
+                <div className="flex space-x-4">
+                    {isAuthenticated && availableLinks.map(link => (
+                        <NavLink
+                            key={link.path}
+                            to={link.path}
+                            className={({ isActive }) =>
+                                `px-3 py-2 rounded-md text-sm font-medium ${isActive ? 'bg-gray-900' : 'hover:bg-gray-700'
+                                }`
+                            }
+                        >
+                            {link.label}
+                        </NavLink>
+                    ))}
+                </div>
+            </div>
+            <div className="flex items-center space-x-4">
+                {isAuthenticated && user && (
+                    <span className="text-sm">Welcome, {user.email}</span>
+                    // TODO: Display current shift info here
+                )}
+                {isAuthenticated ? (
+                    <button onClick={handleLogout} className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
+                        Logout
+                    </button>
+                ) : (
+                    <button onClick={() => navigate('/login')} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+                        Login
+                    </button>
+                )}
+            </div>
+        </nav>
+    );
+};
Index: frontend/src/components/ProtectedRoute.tsx
===================================================================
--- frontend/src/components/ProtectedRoute.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/ProtectedRoute.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,27 @@
+// src/components/ProtectedRoute.tsx
+import { Navigate, Outlet } from 'react-router-dom';
+import { useAuth } from '../hooks/useAuth';
+import { UserType } from '../types/api';
+
+interface ProtectedRouteProps {
+    allowedRoles: UserType[];
+}
+
+export const ProtectedRoute = ({ allowedRoles }: ProtectedRouteProps) => {
+    const { isAuthenticated, isLoading, hasRole } = useAuth();
+
+    if (isLoading) {
+        return <div>Loading...</div>; // Or a spinner component
+    }
+
+    if (!isAuthenticated) {
+        return <Navigate to="/login" replace />;
+    }
+
+    if (!hasRole(allowedRoles)) {
+        console.log("Access denied. User does not have the required role.");
+        return <Navigate to="/" replace />; // Or a dedicated "Unauthorized" page
+    }
+
+    return <Outlet />;
+};
Index: frontend/src/components/employee/CurrentShiftCard.tsx
===================================================================
--- frontend/src/components/employee/CurrentShiftCard.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/employee/CurrentShiftCard.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,130 @@
+// src/components/employee/CurrentShiftCard.tsx
+import { useEffect, useState } from 'react';
+import type { AssignmentDto } from '../../types/api';
+import { assignmentRepository } from '../../api/assignmentRepository';
+import { useAuth } from '../../hooks/useAuth';
+
+export const CurrentShiftCard = () => {
+    const { user } = useAuth();
+    const [assignment, setAssignment] = useState<AssignmentDto | null>(null);
+    const [loading, setLoading] = useState(true);
+    const [error, setError] = useState('');
+    const [isActionLoading, setIsActionLoading] = useState(false);
+
+    useEffect(() => {
+        if (user) {
+            assignmentRepository.getNextShift(user.id)
+                .then(setAssignment)
+                .catch(() => setError('No upcoming shift found.'))
+                .finally(() => setLoading(false));
+        }
+    }, [user]);
+
+    const handleClockIn = async () => {
+        if (!assignment) return;
+        setIsActionLoading(true);
+        try {
+            const updatedAssignment = await assignmentRepository.clockIn(assignment.id);
+            setAssignment(updatedAssignment);
+        } catch (err) {
+            alert('Failed to clock in.');
+            console.error(err);
+        } finally {
+            setIsActionLoading(false);
+        }
+    };
+
+    const handleClockOut = async () => {
+        if (!assignment) return;
+        setIsActionLoading(true);
+        try {
+            const updatedAssignment = await assignmentRepository.clockOut(assignment.id);
+            setAssignment(updatedAssignment);
+        } catch (err) {
+            alert('Failed to clock out.');
+            console.error(err);
+        } finally {
+            setIsActionLoading(false);
+        }
+    };
+
+    const formatTime = (dateString?: string) => {
+        if (!dateString) return 'N/A';
+        return new Date(dateString).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
+    };
+
+    if (loading) return <div>Loading your shift details...</div>;
+    if (error) return <div className="text-center text-gray-500">{error}</div>;
+    if (!assignment) return null;
+
+    const { shift, manager, clock_in_time, clock_out_time } = assignment;
+    const shiftStartTime = new Date(shift.start);
+    const now = new Date();
+    const oneHourBeforeShift = new Date(shiftStartTime.getTime() - 60 * 60 * 1000);
+
+    const isClockInDisabled = now < oneHourBeforeShift;
+    const isClockedIn = !!clock_in_time && !clock_out_time;
+    const isShiftComplete = !!clock_in_time && !!clock_out_time;
+
+    const getActionButton = () => {
+        if (isShiftComplete) {
+            return <p className="text-center font-semibold text-green-600">Shift Completed</p>;
+        }
+        if (isClockedIn) {
+            return (
+                <button
+                    onClick={handleClockOut}
+                    disabled={isActionLoading}
+                    className="w-full bg-red-500 hover:bg-red-700 text-white font-bold py-3 px-4 rounded-lg disabled:bg-gray-400"
+                >
+                    {isActionLoading ? 'Processing...' : 'Clock Out'}
+                </button>
+            );
+        }
+        return (
+            <button
+                onClick={handleClockIn}
+                disabled={isClockInDisabled || isActionLoading}
+                className="w-full bg-green-500 hover:bg-green-700 text-white font-bold py-3 px-4 rounded-lg disabled:bg-gray-400"
+                title={isClockInDisabled ? `You can clock in after ${formatTime(oneHourBeforeShift.toISOString())}` : ''}
+            >
+                {isActionLoading ? 'Processing...' : 'Clock In'}
+            </button>
+        );
+    };
+
+    return (
+        <div className="bg-white p-6 rounded-lg shadow-md max-w-md mx-auto">
+            <h2 className="text-2xl font-bold text-center mb-1">Your Next Shift</h2>
+            <p className="text-center text-gray-500 mb-4">{new Date(shift.date).toLocaleDateString([], { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}</p>
+
+            <div className="grid grid-cols-2 gap-4 text-center my-6">
+                <div>
+                    <p className="text-sm text-gray-500">Shift Starts</p>
+                    <p className="text-xl font-bold">{formatTime(shift.start)}</p>
+                </div>
+                <div>
+                    <p className="text-sm text-gray-500">Shift Ends</p>
+                    <p className="text-xl font-bold">{formatTime(shift.end)}</p>
+                </div>
+                <div>
+                    <p className="text-sm text-gray-500">Clocked In</p>
+                    <p className={`text-xl font-bold ${clock_in_time ? 'text-green-600' : ''}`}>{formatTime(clock_in_time)}</p>
+                </div>
+                <div>
+                    <p className="text-sm text-gray-500">Clocked Out</p>
+                    <p className={`text-xl font-bold ${clock_out_time ? 'text-red-600' : ''}`}>{formatTime(clock_out_time)}</p>
+                </div>
+            </div>
+
+            <div className="text-center mb-6">
+                <p className="text-sm text-gray-500">Manager</p>
+                <p className="text-lg font-semibold">{manager.email}</p>
+            </div>
+
+            <div className="mt-4">
+                {getActionButton()}
+            </div>
+        </div>
+    );
+};
Index: frontend/src/components/forms/AcceptReservationForm.tsx
===================================================================
--- frontend/src/components/forms/AcceptReservationForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/AcceptReservationForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,59 @@
+// src/components/forms/AcceptReservationForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { reservationRepository } from '../../api/reservationRepository';
+
+const acceptReservationSchema = z.object({
+    table_number: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(1, 'Table number is required')
+    ),
+});
+
+type AcceptReservationFormData = z.infer<typeof acceptReservationSchema>;
+
+interface AcceptReservationFormProps {
+    reservationId: number;
+    onSuccess: () => void;
+}
+
+export const AcceptReservationForm = ({ reservationId, onSuccess }: AcceptReservationFormProps) => {
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<AcceptReservationFormData>({
+        resolver: zodResolver(acceptReservationSchema),
+    });
+
+    const onSubmit = async (data: AcceptReservationFormData) => {
+        try {
+            await reservationRepository.acceptReservation(reservationId, data.table_number);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to accept reservation:', error);
+            alert('Failed to accept reservation. Please try again.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)}>
+            <div className="mb-4">
+                <label htmlFor="table_number" className="block text-sm font-medium text-gray-700">Assign Table Number</label>
+                <input
+                    id="table_number"
+                    type="number"
+                    {...register('table_number')}
+                    className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
+                />
+                {errors.table_number && <p className="text-red-500 text-xs mt-1">{errors.table_number.message}</p>}
+            </div>
+            <div className="flex justify-end">
+                <button
+                    type="submit"
+                    disabled={isSubmitting}
+                    className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:bg-gray-400"
+                >
+                    {isSubmitting ? 'Accepting...' : 'Accept Reservation'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/CreateAssignmentForm.tsx
===================================================================
--- frontend/src/components/forms/CreateAssignmentForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/CreateAssignmentForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,100 @@
+// src/components/forms/CreateAssignmentForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { assignmentRepository } from '../../api/assignmentRepository';
+import { useEffect, useState } from 'react';
+import type { EmployeeDto, ShiftDto } from '../../types/api';
+import { employeeRepository } from '../../api/employeeRepository';
+import { shiftRepository } from '../../api/shiftRepository';
+
+const createAssignmentSchema = z.object({
+    employee_id: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(1, 'Please select an employee')
+    ),
+    shift_id: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(1, 'Please select a shift')
+    ),
+});
+
+type CreateAssignmentFormData = z.infer<typeof createAssignmentSchema>;
+
+interface CreateAssignmentFormProps {
+    onSuccess: () => void;
+}
+
+export const CreateAssignmentForm = ({ onSuccess }: CreateAssignmentFormProps) => {
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<CreateAssignmentFormData>({
+        resolver: zodResolver(createAssignmentSchema),
+    });
+
+    const [employees, setEmployees] = useState<EmployeeDto[]>([]);
+    const [shifts, setShifts] = useState<ShiftDto[]>([]);
+
+    useEffect(() => {
+        // Fetch both employees and shifts when the component mounts
+        Promise.all([
+            employeeRepository.getAllEmployees(),
+            shiftRepository.getAllShifts()
+        ]).then(([empData, shiftData]) => {
+            setEmployees(empData);
+            setShifts(shiftData);
+        }).catch(console.error);
+    }, []);
+
+    const onSubmit = async (data: CreateAssignmentFormData) => {
+        try {
+            await assignmentRepository.createAssignment(data);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to create assignment:', error);
+            alert('Failed to create assignment. Please try again.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)}>
+            <div className="mb-4">
+                <label htmlFor="employee_id" className="block text-sm font-medium text-gray-700">Employee</label>
+                <select
+                    id="employee_id"
+                    {...register('employee_id')}
+                    className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
+                >
+                    <option value="">Select Employee</option>
+                    {employees.map(emp => <option key={emp.id} value={emp.id}>{emp.email}</option>)}
+                </select>
+                {errors.employee_id && <p className="text-red-500 text-xs mt-1">{errors.employee_id.message}</p>}
+            </div>
+
+            <div className="mb-4">
+                <label htmlFor="shift_id" className="block text-sm font-medium text-gray-700">Shift</label>
+                <select
+                    id="shift_id"
+                    {...register('shift_id')}
+                    className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
+                >
+                    <option value="">Select Shift</option>
+                    {shifts.map(shift => (
+                        <option key={shift.id} value={shift.id}>
+                            {new Date(shift.date).toLocaleDateString()} ({new Date(shift.start).toLocaleTimeString()} - {new Date(shift.end).toLocaleTimeString()})
+                        </option>
+                    ))}
+                </select>
+                {errors.shift_id && <p className="text-red-500 text-xs mt-1">{errors.shift_id.message}</p>}
+            </div>
+
+            <div className="flex justify-end">
+                <button
+                    type="submit"
+                    disabled={isSubmitting}
+                    className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:bg-gray-400"
+                >
+                    {isSubmitting ? 'Assigning...' : 'Create Assignment'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/CreateCategoryForm.tsx
===================================================================
--- frontend/src/components/forms/CreateCategoryForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/CreateCategoryForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,52 @@
+// src/components/forms/CreateCategoryForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { categoryRepository } from '../../api/categoryRepository';
+
+const createCategorySchema = z.object({
+    name: z.string().min(2, 'Name must be at least 2 characters'),
+    is_available: z.boolean(),
+});
+
+type CreateCategoryFormData = z.infer<typeof createCategorySchema>;
+
+interface CreateCategoryFormProps {
+    onSuccess: () => void;
+}
+
+export const CreateCategoryForm = ({ onSuccess }: CreateCategoryFormProps) => {
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<CreateCategoryFormData>({
+        resolver: zodResolver(createCategorySchema),
+        defaultValues: { is_available: true },
+    });
+
+    const onSubmit = async (data: CreateCategoryFormData) => {
+        try {
+            await categoryRepository.createCategory(data);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to create category:', error);
+            alert('Failed to create category.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
+            <div>
+                <label>Category Name</label>
+                <input {...register('name')} className="w-full p-2 border rounded" />
+                {errors.name && <p className="text-red-500 text-xs">{errors.name.message}</p>}
+            </div>
+            <div className="flex items-center">
+                <input type="checkbox" {...register('is_available')} className="h-4 w-4 rounded" />
+                <label className="ml-2">Is Available</label>
+            </div>
+            <div className="flex justify-end">
+                <button type="submit" disabled={isSubmitting} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+                    {isSubmitting ? 'Creating...' : 'Create Category'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/CreateEmployeeForm.tsx
===================================================================
--- frontend/src/components/forms/CreateEmployeeForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/CreateEmployeeForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,108 @@
+// src/components/forms/CreateEmployeeForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { employeeRepository } from '../../api/employeeRepository';
+import type { CreateEmployeeRequest } from '../../types/api';
+
+const staffRoles = [
+    { id: 1, name: 'Server' },
+    { id: 2, name: 'Chef' },
+    { id: 3, name: 'Bartender' },
+    { id: 4, name: 'Hostess' },
+];
+
+const createEmployeeSchema = z.object({
+    email: z.string().email('Invalid email address'),
+    password: z.string().min(6, 'Password must be at least 6 characters'),
+    employee_type: z.enum(["MANAGER", "FRONT_STAFF", "BACK_STAFF"]),
+    staff_role_id: z.preprocess(
+        (a) => a ? parseInt(z.string().parse(a), 10) : undefined,
+        z.number().optional()
+    ),
+    phone_number: z.string().optional(),
+    gross_salary: z.number().min(0, 'Gross salary must be non-negative').optional().default(0),
+    net_salary: z.number().min(0, 'Net salary must be non-negative').optional().default(0),
+    // Add other fields from CreateEmployeeRequest as needed
+});
+
+type CreateEmployeeFormData = z.infer<typeof createEmployeeSchema>;
+
+interface CreateEmployeeFormProps {
+    onSuccess: () => void;
+}
+
+export const CreateEmployeeForm = ({ onSuccess }: CreateEmployeeFormProps) => {
+    const { register, handleSubmit, watch, formState: { errors, isSubmitting } } = useForm<CreateEmployeeFormData>({
+        resolver: zodResolver(createEmployeeSchema),
+    });
+
+    const employeeType = watch('employee_type');
+
+    const onSubmit = async (data: CreateEmployeeFormData) => {
+        try {
+            const employeeData: CreateEmployeeRequest = { ...data };
+            await employeeRepository.createEmployee(employeeData);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to create employee:', error);
+            alert('Failed to create employee. Please try again.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
+            <div>
+                <label>Email</label>
+                <input {...register('email')} className="w-full p-2 border rounded" />
+                {errors.email && <p className="text-red-500 text-xs">{errors.email.message}</p>}
+            </div>
+            <div>
+                <label>Password</label>
+                <input type="password" {...register('password')} className="w-full p-2 border rounded" />
+                {errors.password && <p className="text-red-500 text-xs">{errors.password.message}</p>}
+            </div>
+            <div>
+                <label>Employee Type</label>
+                <select {...register('employee_type')} className="w-full p-2 border rounded">
+                    <option value="">Select Type</option>
+                    <option value="MANAGER">Manager</option>
+                    <option value="FRONT_STAFF">Front Staff</option>
+                    <option value="BACK_STAFF">Back Staff</option>
+                </select>
+                {errors.employee_type && <p className="text-red-500 text-xs">{errors.employee_type.message}</p>}
+            </div>
+
+            {employeeType !== 'MANAGER' && (
+                <div>
+                    <label>Staff Role</label>
+                    <select {...register('staff_role_id')} className="w-full p-2 border rounded">
+                        <option value="">Select Role</option>
+                        {staffRoles.map(role => <option key={role.id} value={role.id}>{role.name}</option>)}
+                    </select>
+                    {errors.staff_role_id && <p className="text-red-500 text-xs">{errors.staff_role_id.message}</p>}
+                </div>
+            )}
+
+            <div>
+                <label>Phone Number</label>
+                <input {...register('phone_number')} className="w-full p-2 border rounded" />
+            </div>
+            <div>
+                <label>Gross Salary ($)</label>
+                <input type="number" {...register('gross_salary', { valueAsNumber: true })} className="w-full p-2 border rounded" />
+
+            </div>
+            <div>
+                <label>Net Salary ($)</label>
+                <input type="number" {...register('net_salary', { valueAsNumber: true })} className="w-full p-2 border rounded" />
+            </div>
+
+            <div className="flex justify-end">
+                <button type="submit" disabled={isSubmitting} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+                    {isSubmitting ? 'Creating...' : 'Create Employee'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/CreateProductForm.tsx
===================================================================
--- frontend/src/components/forms/CreateProductForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/CreateProductForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,96 @@
+// src/components/forms/CreateProductForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { productRepository } from '../../api/productRepository';
+import { useEffect, useState } from 'react';
+import type { CategoryDto } from '../../types/api';
+import { categoryRepository } from '../../api/categoryRepository';
+
+const createProductSchema = z.object({
+    name: z.string().min(2, 'Name must be at least 2 characters'),
+    price: z.preprocess(
+        (a) => parseFloat(z.string().parse(a)),
+        z.number().positive('Price must be positive')
+    ),
+    // description: z.string().min(10, 'Description must be at least 10 characters'),
+    category_id: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(1, 'Please select a category')
+    ),
+    tax_class: z.string().default('A'),
+    manage_inventory: z.boolean().default(false),
+});
+
+type CreateProductFormData = z.infer<typeof createProductSchema>;
+
+interface CreateProductFormProps {
+    onSuccess: () => void;
+}
+
+export const CreateProductForm = ({ onSuccess }: CreateProductFormProps) => {
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<CreateProductFormData>({
+        resolver: zodResolver(createProductSchema),
+    });
+
+    const [categories, setCategories] = useState<CategoryDto[]>([]);
+
+    useEffect(() => {
+        categoryRepository.getAllCategories().then(setCategories).catch(console.error);
+    }, []);
+
+    const onSubmit = async (data: CreateProductFormData) => {
+        try {
+            await productRepository.createProduct(data);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to create product:', error);
+            alert('Failed to create product.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
+            <div>
+                <label>Product Name</label>
+                <input {...register('name')} className="w-full p-2 border rounded" />
+                {errors.name && <p className="text-red-500 text-xs">{errors.name.message}</p>}
+            </div>
+            <div>
+                <label>Price ($)</label>
+                <input type="number" step="0.01" {...register('price')} className="w-full p-2 border rounded" />
+                {errors.price && <p className="text-red-500 text-xs">{errors.price.message}</p>}
+            </div>
+            <div>
+                <label>Category</label>
+                <select {...register('category_id')} className="w-full p-2 border rounded">
+                    <option value="">Select a category</option>
+                    {categories.filter(c => c.is_available).map(cat => (
+                        <option key={cat.id} value={cat.id}>{cat.name}</option>
+                    ))}
+                </select>
+                {errors.category_id && <p className="text-red-500 text-xs">{errors.category_id.message}</p>}
+            </div>
+            <div>
+                <label>Tax Class</label>
+                <select {...register('tax_class')} className="w-full p-2 border rounded">
+                    <option value="A">A - 10%</option>
+                    <option value="B">B - 5%</option>
+                    <option value="C">C - 0%</option>
+                    <option value="D">D - 18%</option>
+                </select>
+                {errors.category_id && <p className="text-red-500 text-xs">{errors.category_id.message}</p>}
+            </div>
+
+            <div>
+                <input type="checkbox" {...register('manage_inventory')} className="mr-2" />
+                <label>Manage Inventory</label>
+            </div>
+            <div className="flex justify-end">
+                <button type="submit" disabled={isSubmitting} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+                    {isSubmitting ? 'Creating...' : 'Create Product'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/CreateReservationForm.tsx
===================================================================
--- frontend/src/components/forms/CreateReservationForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/CreateReservationForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,76 @@
+// src/components/forms/CreateReservationForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { reservationRepository } from '../../api/reservationRepository';
+import type { CreateReservationDto } from '../../types/api';
+
+const createReservationSchema = z.object({
+    number_of_people: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(1, 'At least one person is required')
+    ),
+    stay_length: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(30, 'Minimum stay is 30 minutes')
+    ),
+    date: z.string().min(1, 'Date is required'),
+    time: z.string().min(1, 'Time is required'),
+});
+
+type CreateReservationFormData = z.infer<typeof createReservationSchema>;
+
+interface CreateReservationFormProps {
+    onSuccess: () => void;
+}
+
+export const CreateReservationForm = ({ onSuccess }: CreateReservationFormProps) => {
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<CreateReservationFormData>({
+        resolver: zodResolver(createReservationSchema),
+    });
+
+    const onSubmit = async (data: CreateReservationFormData) => {
+        try {
+            const reservationData: CreateReservationDto = {
+                number_of_people: data.number_of_people,
+                stay_length: data.stay_length,
+                datetime: `${data.date}T${data.time}:00`,
+            };
+            await reservationRepository.createReservation(reservationData);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to create reservation:', error);
+            alert('Failed to create reservation. Please try again.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
+            <div>
+                <label>Number of People</label>
+                <input type="number" {...register('number_of_people')} className="w-full p-2 border rounded" />
+                {errors.number_of_people && <p className="text-red-500 text-xs">{errors.number_of_people.message}</p>}
+            </div>
+            <div>
+                <label>Stay Length (in minutes)</label>
+                <input type="number" step="15" {...register('stay_length')} className="w-full p-2 border rounded" />
+                {errors.stay_length && <p className="text-red-500 text-xs">{errors.stay_length.message}</p>}
+            </div>
+            <div>
+                <label>Date</label>
+                <input type="date" {...register('date')} className="w-full p-2 border rounded" />
+                {errors.date && <p className="text-red-500 text-xs">{errors.date.message}</p>}
+            </div>
+            <div>
+                <label>Time</label>
+                <input type="time" {...register('time')} className="w-full p-2 border rounded" />
+                {errors.time && <p className="text-red-500 text-xs">{errors.time.message}</p>}
+            </div>
+            <div className="flex justify-end">
+                <button type="submit" disabled={isSubmitting} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+                    {isSubmitting ? 'Creating...' : 'Create Reservation'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/CreateShiftForm.tsx
===================================================================
--- frontend/src/components/forms/CreateShiftForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/CreateShiftForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,64 @@
+// src/components/forms/CreateShiftForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { shiftRepository } from '../../api/shiftRepository';
+import type { CreateShiftDto } from '../../types/api';
+
+const createShiftSchema = z.object({
+    date: z.string().min(1, 'Date is required'),
+    startTime: z.string().min(1, 'Start time is required'),
+    endTime: z.string().min(1, 'End time is required'),
+});
+
+type CreateShiftFormData = z.infer<typeof createShiftSchema>;
+
+interface CreateShiftFormProps {
+    onSuccess: () => void;
+}
+
+export const CreateShiftForm = ({ onSuccess }: CreateShiftFormProps) => {
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<CreateShiftFormData>({
+        resolver: zodResolver(createShiftSchema),
+    });
+
+    const onSubmit = async (data: CreateShiftFormData) => {
+        try {
+            const shiftData: CreateShiftDto = {
+                date: data.date,
+                start: `${data.date}T${data.startTime}:00`,
+                end: `${data.date}T${data.endTime}:00`,
+            };
+            await shiftRepository.createShift(shiftData);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to create shift:', error);
+            alert('Failed to create shift. Please try again.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
+            <div>
+                <label>Date</label>
+                <input type="date" {...register('date')} className="w-full p-2 border rounded" />
+                {errors.date && <p className="text-red-500 text-xs">{errors.date.message}</p>}
+            </div>
+            <div>
+                <label>Start Time</label>
+                <input type="time" {...register('startTime')} className="w-full p-2 border rounded" />
+                {errors.startTime && <p className="text-red-500 text-xs">{errors.startTime.message}</p>}
+            </div>
+            <div>
+                <label>End Time</label>
+                <input type="time" {...register('endTime')} className="w-full p-2 border rounded" />
+                {errors.endTime && <p className="text-red-500 text-xs">{errors.endTime.message}</p>}
+            </div>
+            <div className="flex justify-end">
+                <button type="submit" disabled={isSubmitting} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+                    {isSubmitting ? 'Creating...' : 'Create Shift'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/CreateTabOrderForm.tsx
===================================================================
--- frontend/src/components/forms/CreateTabOrderForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/CreateTabOrderForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,67 @@
+// src/components/forms/CreateTabOrderForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { orderRepository } from '../../api/orderRepository';
+import type { CreateOrderDto } from '../../types/api';
+
+const createOrderSchema = z.object({
+    table_number: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(1, 'Table number is required')
+    ),
+    // For MVP, we'll create an empty tab. Items can be added later.
+});
+
+type CreateOrderFormData = z.infer<typeof createOrderSchema>;
+
+interface CreateTabOrderFormProps {
+    onSuccess: () => void;
+}
+
+export const CreateTabOrderForm = ({ onSuccess }: CreateTabOrderFormProps) => {
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<CreateOrderFormData>({
+        resolver: zodResolver(createOrderSchema),
+    });
+
+    const onSubmit = async (data: CreateOrderFormData) => {
+        try {
+            const newOrderData: CreateOrderDto = {
+                table_number: data.table_number,
+                type: 'TAB',
+                status: 'PENDING',
+                order_items: [], // Start with an empty order
+            };
+            await orderRepository.createTabOrder(newOrderData);
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to create tab order:', error);
+            alert('Failed to create tab. Please try again.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)}>
+            <div className="mb-4">
+                <label htmlFor="table_number" className="block text-sm font-medium text-gray-700">Table Number</label>
+                <input
+                    id="table_number"
+                    type="number"
+                    {...register('table_number')}
+                    className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
+                />
+                {errors.table_number && <p className="text-red-500 text-xs mt-1">{errors.table_number.message}</p>}
+            </div>
+
+            <div className="flex justify-end">
+                <button
+                    type="submit"
+                    disabled={isSubmitting}
+                    className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:bg-gray-400"
+                >
+                    {isSubmitting ? 'Creating...' : 'Create Tab'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/forms/UpdateTableNumberForm.tsx
===================================================================
--- frontend/src/components/forms/UpdateTableNumberForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/forms/UpdateTableNumberForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,52 @@
+// src/components/forms/UpdateTableNumberForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import type { OrderDto } from '../../types/api';
+import { orderRepository } from '../../api/orderRepository';
+
+const updateTableSchema = z.object({
+    table_number: z.preprocess(
+        (a) => parseInt(z.string().parse(a), 10),
+        z.number().min(1, 'Invalid table number')
+    ),
+});
+
+type UpdateTableFormData = z.infer<typeof updateTableSchema>;
+
+interface UpdateTableNumberFormProps {
+    order: OrderDto;
+    onSuccess: () => void;
+}
+
+export const UpdateTableNumberForm = ({ order, onSuccess }: UpdateTableNumberFormProps) => {
+    const { register, handleSubmit, formState: { isSubmitting } } = useForm<UpdateTableFormData>({
+        resolver: zodResolver(updateTableSchema),
+        defaultValues: { table_number: order.table_number },
+    });
+
+    const onSubmit = async (data: UpdateTableFormData) => {
+        try {
+            const updatedOrderData = { ...order, table_number: data.table_number };
+            await orderRepository.updateOrder(updatedOrderData);
+            alert('Table number updated successfully!');
+            onSuccess();
+        } catch (error) {
+            console.error('Failed to update table number:', error);
+            alert('Failed to update table number.');
+        }
+    };
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)} className="flex items-center space-x-2">
+            <input
+                type="number"
+                {...register('table_number')}
+                className="p-1 border rounded w-20"
+            />
+            <button type="submit" disabled={isSubmitting} className="bg-gray-200 hover:bg-gray-300 text-black text-xs font-bold py-1 px-2 rounded">
+                {isSubmitting ? '...' : 'Save'}
+            </button>
+        </form>
+    );
+};
Index: frontend/src/components/order/UpdateOrderStatusActions.tsx
===================================================================
--- frontend/src/components/order/UpdateOrderStatusActions.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/order/UpdateOrderStatusActions.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,61 @@
+// src/components/order/UpdateOrderStatusActions.tsx
+import { useState } from 'react';
+import type { OrderDto } from '../../types/api';
+import { orderRepository } from '../../api/orderRepository';
+
+interface UpdateOrderStatusActionsProps {
+    order: OrderDto;
+    onSuccess: () => void;
+}
+
+const availableStatuses = ["PENDING", "CONFIRMED", "COMPLETED", "CANCELED"];
+
+export const UpdateOrderStatusActions = ({ order, onSuccess }: UpdateOrderStatusActionsProps) => {
+    const [loadingStatus, setLoadingStatus] = useState<string | null>(null);
+
+    const handleChangeStatus = async (newStatus: string) => {
+        setLoadingStatus(newStatus);
+        try {
+            await orderRepository.updateOrderStatus(order.id, newStatus);
+            onSuccess();
+        } catch (error) {
+            console.error(`Failed to update status to ${newStatus}:`, error);
+            alert('Failed to update status.');
+        } finally {
+            setLoadingStatus(null);
+        }
+    };
+
+    // Don't show actions for completed or canceled orders
+    if (order.status === 'COMPLETED' || order.status === 'CANCELED') {
+        return null;
+    }
+
+    return (
+        <div className="mt-4 pt-4">
+            <h3 className="text-md font-semibold mb-2">Actions</h3>
+            <div className="flex flex-wrap gap-2">
+                {availableStatuses.map(status => {
+                    // Don't show a button for the current status
+                    if (status === order.status) return null;
+
+                    return (
+                        <button
+                            key={status}
+                            onClick={() => handleChangeStatus(status)}
+                            disabled={!!loadingStatus}
+                            className={`text-white font-bold py-1 px-3 rounded text-sm disabled:bg-gray-400
+                ${status === 'COMPLETED' ? 'bg-green-500 hover:bg-green-700' : ''}
+                ${status === 'CANCELED' ? 'bg-red-500 hover:bg-red-700' : ''}
+                ${status === 'CONFIRMED' ? 'bg-yellow-500 hover:bg-yellow-600' : ''}
+                ${status === 'PENDING' ? 'bg-blue-500 hover:bg-blue-700' : ''}
+              `}
+                        >
+                            {loadingStatus === status ? 'Updating...' : `Mark as ${status.replace('_', ' ')}`}
+                        </button>
+                    )
+                })}
+            </div>
+        </div>
+    );
+};
Index: frontend/src/components/public/CartSidebar.tsx
===================================================================
--- frontend/src/components/public/CartSidebar.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/public/CartSidebar.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,57 @@
+// src/components/public/CartSidebar.tsx
+// src/components/public/CartSidebar.tsx
+import type { ProductDto } from '../../types/api';
+
+interface CartItem extends ProductDto {
+    quantity: number;
+}
+
+interface CartSidebarProps {
+    cart: Record<number, CartItem>;
+    onUpdateQuantity: (product: ProductDto, change: 1 | -1) => void;
+    onCheckout: () => void;
+}
+
+export const CartSidebar = ({ cart, onUpdateQuantity, onCheckout }: CartSidebarProps) => {
+    const cartItems = Object.values(cart);
+    const total = cartItems.reduce((sum, item) => sum + item.price * item.quantity, 0);
+
+    if (cartItems.length === 0) {
+        return (
+            <div className="bg-white p-4 rounded-lg shadow-lg h-full">
+                <h3 className="text-xl font-bold border-b pb-2">Your Order</h3>
+                <p className="text-gray-500 mt-4">Your cart is empty. Add items from the menu to get started!</p>
+            </div>
+        );
+    }
+
+    return (
+        <div className="bg-white p-4 rounded-lg shadow-lg h-full flex flex-col">
+            <h3 className="text-xl font-bold border-b pb-2">Your Order</h3>
+            <div className="flex-grow my-4 space-y-3 overflow-y-auto">
+                {cartItems.map(item => (
+                    <div key={item.id} className="flex justify-between items-center">
+                        <div>
+                            <p className="font-semibold">{item.name}</p>
+                            <p className="text-sm text-gray-600">${item.price.toFixed(2)}</p>
+                        </div>
+                        <div className="flex items-center space-x-2">
+                            <button onClick={() => onUpdateQuantity(item, -1)} className="font-bold">-</button>
+                            <span>{item.quantity}</span>
+                            <button onClick={() => onUpdateQuantity(item, 1)} className="font-bold">+</button>
+                        </div>
+                    </div>
+                ))}
+            </div>
+            <div className="border-t pt-4">
+                <div className="flex justify-between font-bold text-lg mb-4">
+                    <span>Total</span>
+                    <span>${total.toFixed(2)}</span>
+                </div>
+                <button onClick={onCheckout} className="w-full bg-green-500 hover:bg-green-600 text-white font-bold py-3 rounded-lg">
+                    Checkout
+                </button>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/components/public/CheckoutForm.tsx
===================================================================
--- frontend/src/components/public/CheckoutForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/public/CheckoutForm.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,37 @@
+// src/components/forms/CheckoutForm.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+
+const checkoutSchema = z.object({
+    delivery_address: z.string().min(10, 'Please enter a valid address'),
+});
+
+type CheckoutFormData = z.infer<typeof checkoutSchema>;
+
+interface CheckoutFormProps {
+    onSubmit: (data: CheckoutFormData) => void;
+    isSubmitting: boolean;
+}
+
+export const CheckoutForm = ({ onSubmit, isSubmitting }: CheckoutFormProps) => {
+    const { register, handleSubmit, formState: { errors } } = useForm<CheckoutFormData>({
+        resolver: zodResolver(checkoutSchema),
+    });
+
+    return (
+        <form onSubmit={handleSubmit(onSubmit)}>
+            <p className="mb-4">Please provide your delivery address to complete the order.</p>
+            <div className="mb-4">
+                <label>Delivery Address</label>
+                <textarea {...register('delivery_address')} rows={3} className="w-full p-2 border rounded" />
+                {errors.delivery_address && <p className="text-red-500 text-xs">{errors.delivery_address.message}</p>}
+            </div>
+            <div className="flex justify-end">
+                <button type="submit" disabled={isSubmitting} className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded">
+                    {isSubmitting ? 'Placing Order...' : 'Confirm Order'}
+                </button>
+            </div>
+        </form>
+    );
+};
Index: frontend/src/components/public/PublicNavbar.tsx
===================================================================
--- frontend/src/components/public/PublicNavbar.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/components/public/PublicNavbar.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,45 @@
+// src/components/public/PublicNavbar.tsx
+import { NavLink, useNavigate } from 'react-router-dom';
+import { useAuth } from '../../hooks/useAuth';
+
+export const PublicNavbar = () => {
+    const { isAuthenticated, logout, user } = useAuth();
+    const navigate = useNavigate();
+
+    const handleLogout = () => {
+        logout();
+        navigate('/');
+    };
+
+    return (
+        <nav className="bg-white shadow-md text-gray-800 p-4 flex justify-between items-center">
+            <NavLink to="/" className="text-2xl font-bold text-blue-600">TastyTabs</NavLink>
+            <div className="flex items-center space-x-4">
+                <NavLink to="/" className={({ isActive }) => `hover:text-blue-600 ${isActive ? 'font-semibold' : ''}`}>Menu</NavLink>
+                {isAuthenticated && (
+                    <>
+                        <NavLink to="/my-orders" className={({ isActive }) => `hover:text-blue-600 ${isActive ? 'font-semibold' : ''}`}>My Orders</NavLink>
+                        <NavLink to="/my-reservations" className={({ isActive }) => `hover:text-blue-600 ${isActive ? 'font-semibold' : ''}`}>My Reservations</NavLink>
+                    </>
+                )}
+                {isAuthenticated ? (
+                    <>
+                        <span className="text-sm">Hi, {user?.email}</span>
+                        <button onClick={handleLogout} className="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-3 rounded-md text-sm">
+                            Logout
+                        </button>
+                    </>
+                ) : (
+                    <div className="space-x-2">
+                        <button onClick={() => navigate('/login')} className="bg-gray-200 hover:bg-gray-300 text-black font-bold py-2 px-3 rounded-md text-sm">
+                            Login
+                        </button>
+                        <button onClick={() => navigate('/register')} className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-3 rounded-md text-sm">
+                            Register
+                        </button>
+                    </div>
+                )}
+            </div>
+        </nav>
+    );
+};
Index: frontend/src/context/AuthContext.tsx
===================================================================
--- frontend/src/context/AuthContext.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/context/AuthContext.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,76 @@
+// src/context/AuthContext.tsx
+import { createContext, useState, useEffect, type ReactNode } from 'react';
+import { type UserDto, type AuthRequest, UserType } from '../types/api';
+import { authRepository } from '../api/authRepository';
+
+interface AuthContextType {
+    user: UserDto | null;
+    token: string | null;
+    isAuthenticated: boolean;
+    isLoading: boolean;
+    login: (credentials: AuthRequest) => Promise<UserDto>; // Changed return type
+    logout: () => void;
+    hasRole: (roles: UserType[]) => boolean;
+}
+
+const AuthContext = createContext<AuthContextType | undefined>(undefined);
+
+interface AuthProviderProps {
+    children: ReactNode;
+}
+
+export const AuthProvider = ({ children }: AuthProviderProps) => {
+    const [user, setUser] = useState<UserDto | null>(null);
+    const [token, setToken] = useState<string | null>(localStorage.getItem('authToken'));
+    const [isLoading, setIsLoading] = useState(true);
+
+    useEffect(() => {
+        const storedToken = localStorage.getItem('authToken');
+        const storedUser = localStorage.getItem('user');
+
+        if (storedToken && storedUser) {
+            setToken(storedToken);
+            setUser(JSON.parse(storedUser));
+        }
+        setIsLoading(false);
+
+    }, []);
+
+    const login = async (credentials: AuthRequest): Promise<UserDto> => { // Changed return type
+        const response = await authRepository.login(credentials);
+        localStorage.setItem('authToken', response.token);
+        localStorage.setItem('user', JSON.stringify(response.user));
+        setToken(response.token);
+        setUser(response.user);
+        return response.user; // Return the user object
+    };
+
+    const logout = () => {
+        localStorage.removeItem('authToken');
+        localStorage.removeItem('user');
+        setToken(null);
+        setUser(null);
+    };
+
+    const hasRole = (roles: UserType[]): boolean => {
+        console.log("Checking roles:", roles, "for user:", user);
+        return user ? roles.includes(user.user_type) : false;
+    };
+
+    return (
+        <AuthContext.Provider value={{
+            user,
+            token,
+            isAuthenticated: !!token,
+            isLoading,
+            login,
+            logout,
+            hasRole,
+        }}>
+            {children}
+        </AuthContext.Provider>
+    );
+};
+
+export default AuthContext;
+
Index: frontend/src/hooks/useAuth.ts
===================================================================
--- frontend/src/hooks/useAuth.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/hooks/useAuth.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,11 @@
+// src/hooks/useAuth.ts
+import { useContext } from "react";
+import AuthContext from "../context/AuthContext";
+
+export const useAuth = () => {
+  const context = useContext(AuthContext);
+  if (context === undefined) {
+    throw new Error("useAuth must be used within an AuthProvider");
+  }
+  return context;
+};
Index: frontend/src/index.css
===================================================================
--- frontend/src/index.css	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/index.css	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,31 @@
+@import "tailwindcss";
+
+:root {
+    font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+    line-height: 1.5;
+    font-weight: 400;
+
+    color-scheme: light dark;
+    color: rgba(0, 0, 0, 0.87);
+    background-color: #ececec;
+
+    font-synthesis: none;
+    text-rendering: optimizeLegibility;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+}
+
+@media (prefers-color-scheme: light) {
+    :root {
+        color: #213547;
+        background-color: #ffffff;
+    }
+
+    a:hover {
+        color: #747bff;
+    }
+
+    button {
+        background-color: #f9f9f9;
+    }
+}
Index: frontend/src/main.tsx
===================================================================
--- frontend/src/main.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/main.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.tsx'
+
+createRoot(document.getElementById('root')!).render(
+  <StrictMode>
+    <App />
+  </StrictMode>,
+)
Index: frontend/src/pages/AssignmentsPage.tsx
===================================================================
--- frontend/src/pages/AssignmentsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/AssignmentsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,58 @@
+// src/pages/AssignmentsPage.tsx
+import { useEffect, useState } from 'react';
+import type { AssignmentDto } from '../types/api';
+import { assignmentRepository } from '../api/assignmentRepository';
+import { Modal } from '../components/Modal';
+import { CreateAssignmentForm } from '../components/forms/CreateAssignmentForm';
+
+export const AssignmentsPage = () => {
+    const [assignments, setAssignments] = useState<AssignmentDto[]>([]);
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchAssignments = () => {
+        assignmentRepository.getAllAssignments()
+            .then(setAssignments)
+            .catch(console.error);
+    };
+
+    useEffect(() => {
+        fetchAssignments();
+    }, []);
+
+    const handleFormSuccess = () => {
+        setIsModalOpen(false);
+        fetchAssignments();
+    };
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">Employee Assignments</h1>
+                <button
+                    onClick={() => setIsModalOpen(true)}
+                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
+                >
+                    + Create Assignment
+                </button>
+            </div>
+
+            <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title="Create New Assignment">
+                <CreateAssignmentForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            <div className="bg-white shadow-md rounded-lg p-4">
+                <h2 className="text-xl font-semibold mb-2">Current Assignments</h2>
+                <ul>
+                    {assignments.map(a => (
+                        <li key={a.id} className="border-b py-2">
+                            <span className="font-semibold">{a.employee.email}</span> is assigned to shift on{' '}
+                            <span className="font-semibold">{new Date(a.shift.date).toLocaleDateString()}</span> from{' '}
+                            <span className="font-semibold">{new Date(a.shift.start).toLocaleTimeString()}</span> to{' '}
+                            <span className="font-semibold">{new Date(a.shift.end).toLocaleTimeString()}</span>
+                        </li>
+                    ))}
+                </ul>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/CategoriesPage.tsx
===================================================================
--- frontend/src/pages/CategoriesPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/CategoriesPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,90 @@
+// src/pages/CategoriesPage.tsx
+import { useEffect, useState } from 'react';
+import type { CategoryDto } from '../types/api';
+import { categoryRepository } from '../api/categoryRepository';
+import { Modal } from '../components/Modal';
+import { CreateCategoryForm } from '../components/forms/CreateCategoryForm';
+
+export const CategoriesPage = () => {
+    const [categories, setCategories] = useState<CategoryDto[]>([]);
+    const [loading, setLoading] = useState(true);
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchCategories = () => {
+        setLoading(true);
+        categoryRepository.getAllCategories()
+            .then(setCategories)
+            .catch(console.error)
+            .finally(() => setLoading(false));
+    };
+
+    useEffect(() => {
+        fetchCategories();
+    }, []);
+
+    const handleFormSuccess = () => {
+        setIsModalOpen(false);
+        fetchCategories();
+    };
+
+    const handleDelete = async (categoryId: number) => {
+        if (window.confirm('Are you sure you want to delete this category? This may affect existing products.')) {
+            try {
+                await categoryRepository.deleteCategory(categoryId);
+                alert('Category deleted successfully!');
+                fetchCategories();
+            } catch (error) {
+                console.error('Failed to delete category:', error);
+                alert('Failed to delete category.');
+            }
+        }
+    };
+
+    if (loading) return <div>Loading categories...</div>;
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">Categories</h1>
+                <button
+                    onClick={() => setIsModalOpen(true)}
+                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
+                >
+                    + Add Category
+                </button>
+            </div>
+
+            <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title="Create New Category">
+                <CreateCategoryForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            <div className="bg-white shadow-md rounded-lg overflow-hidden">
+                <table className="min-w-full leading-normal">
+                    <thead>
+                        <tr>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Name</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Status</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100"></th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {categories.map(cat => (
+                            <tr key={cat.id}>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm font-semibold">{cat.name}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
+                                    {cat.is_available ?
+                                        <span className="text-green-600">Available</span> :
+                                        <span className="text-red-600">Unavailable</span>
+                                    }
+                                </td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm text-right">
+                                    <button onClick={() => handleDelete(cat.id)} className="text-red-600 hover:text-red-900">Delete</button>
+                                </td>
+                            </tr>
+                        ))}
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/DashboardPage.tsx
===================================================================
--- frontend/src/pages/DashboardPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/DashboardPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,45 @@
+// src/pages/DashboardPage.tsx
+import { useAuth } from '../hooks/useAuth';
+import { ROLES } from '../utils/roles';
+import { CurrentShiftCard } from '../components/employee/CurrentShiftCard';
+
+// This is the Manager's dashboard view
+const ManagerDashboard = () => (
+    <>
+        <h1 className="text-3xl font-bold">Manager Dashboard</h1>
+        <p className="mt-2">Welcome back! Here's a summary of today's operations.</p>
+        <div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-4">
+            <div className="bg-white p-6 rounded-lg shadow-md">
+                <h2 className="text-xl font-semibold">Open Orders</h2>
+                <p className="mt-2 text-gray-600">View and manage all incoming and in-progress orders.</p>
+            </div>
+            <div className="bg-white p-6 rounded-lg shadow-md">
+                <h2 className="text-xl font-semibold">Today's Reservations</h2>
+                <p className="mt-2 text-gray-600">See all scheduled reservations for today.</p>
+            </div>
+        </div>
+    </>
+);
+
+// This is the Employee's dashboard view
+const EmployeeDashboard = () => (
+    <>
+        <h1 className="text-3xl font-bold mb-6">Dashboard</h1>
+        <CurrentShiftCard />
+    </>
+);
+
+const DashboardPage = () => {
+    const { user } = useAuth();
+
+    // Determine which dashboard to show based on user role
+    const isManager = user?.user_type === ROLES.MANAGER;
+
+    return (
+        <div className="p-6">
+            {isManager ? <ManagerDashboard /> : <EmployeeDashboard />}
+        </div>
+    );
+};
+
+export default DashboardPage;
Index: frontend/src/pages/EmployeesPage.tsx
===================================================================
--- frontend/src/pages/EmployeesPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/EmployeesPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,72 @@
+// src/pages/EmployeesPage.tsx
+import { useEffect, useState } from 'react';
+import type { EmployeeDto } from '../types/api';
+import { employeeRepository } from '../api/employeeRepository';
+import { Modal } from '../components/Modal';
+import { CreateEmployeeForm } from '../components/forms/CreateEmployeeForm';
+
+export const EmployeesPage = () => {
+    const [employees, setEmployees] = useState<EmployeeDto[]>([]);
+    const [loading, setLoading] = useState(true);
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchEmployees = () => {
+        setLoading(true);
+        employeeRepository.getAllEmployees()
+            .then(setEmployees)
+            .catch(console.error)
+            .finally(() => setLoading(false));
+    };
+
+    useEffect(() => {
+        fetchEmployees();
+    }, []);
+
+    const handleFormSuccess = () => {
+        setIsModalOpen(false);
+        fetchEmployees();
+    };
+
+    if (loading) return <div>Loading employees...</div>;
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">Employees</h1>
+                <button
+                    onClick={() => setIsModalOpen(true)}
+                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
+                >
+                    + Add Employee
+                </button>
+            </div>
+
+            <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title="Create New Employee">
+                <CreateEmployeeForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            <div className="bg-white shadow-md rounded-lg overflow-hidden">
+                <table className="min-w-full leading-normal">
+                    <thead>
+                        <tr>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Email</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Role</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Phone Number</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Gross/Net Salary</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {employees.map(emp => (
+                            <tr key={emp.id}>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">{emp.email}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">{emp.user_type}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">{emp.phone_number}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">${emp.gross_salary} / ${emp.net_salary}</td>
+                            </tr>
+                        ))}
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/LoginPage.tsx
===================================================================
--- frontend/src/pages/LoginPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/LoginPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,79 @@
+// src/pages/LoginPage.tsx
+import React, { useState } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { useAuth } from '../hooks/useAuth';
+import { UserType } from '../types/api'; // Import UserType enum
+
+export const LoginPage = () => {
+    const [username, setUsername] = useState('');
+    const [password, setPassword] = useState('');
+    const [error, setError] = useState('');
+    const { login } = useAuth();
+    const navigate = useNavigate();
+
+    const handleSubmit = async (e: React.FormEvent) => {
+        e.preventDefault();
+        setError('');
+        try {
+            const user = await login({ username, password }); // Capture the returned user object
+
+            // Check the user's role and navigate
+            if ([UserType.MANAGER, UserType.FRONT_STAFF, UserType.BACK_STAFF].includes(user.user_type)) {
+                navigate('/admin'); // Navigate to the admin dashboard
+            } else {
+                navigate('/'); // Navigate to the public menu page for customers
+            }
+
+        } catch (err) {
+            setError('Failed to log in. Please check your credentials.');
+            console.error(err);
+        }
+    };
+
+    return (
+        // ... JSX for the login form remains the same ...
+        <div className="min-h-screen flex items-center justify-center bg-gray-100">
+            <div className="bg-white p-8 rounded-lg shadow-md w-full max-w-md">
+                <h2 className="text-2xl font-bold mb-6 text-center">Login</h2>
+                <form onSubmit={handleSubmit}>
+                    {/* Form fields */}
+                    <div className="mb-4">
+                        <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="email">
+                            Email
+                        </label>
+                        <input
+                            id="email"
+                            type="email"
+                            value={username}
+                            onChange={(e) => setUsername(e.target.value)}
+                            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
+                            required
+                        />
+                    </div>
+                    <div className="mb-6">
+                        <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="password">
+                            Password
+                        </label>
+                        <input
+                            id="password"
+                            type="password"
+                            value={password}
+                            onChange={(e) => setPassword(e.target.value)}
+                            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
+                            required
+                        />
+                    </div>
+                    {error && <p className="text-red-500 text-xs italic mb-4">{error}</p>}
+                    <div className="flex items-center justify-between">
+                        <button
+                            type="submit"
+                            className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full"
+                        >
+                            Sign In
+                        </button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/OrderDetailsPage.tsx
===================================================================
--- frontend/src/pages/OrderDetailsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/OrderDetailsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,111 @@
+// src/pages/OrderDetailsPage.tsx
+import { useCallback, useEffect, useState } from 'react';
+import { useParams, Link } from 'react-router-dom';
+import type { OrderDto } from '../types/api';
+import { orderRepository } from '../api/orderRepository';
+import { AddItemModal } from '../components/AddItemModal';
+import { UpdateOrderStatusActions } from '../components/order/UpdateOrderStatusActions';
+
+export const OrderDetailsPage = () => {
+    const { orderId } = useParams<{ orderId: string }>();
+    const [order, setOrder] = useState<OrderDto | null>(null);
+    const [loading, setLoading] = useState(true);
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchOrderDetails = useCallback(() => {
+        if (orderId) {
+            setLoading(true);
+            orderRepository.getOrderById(parseInt(orderId, 10))
+                .then(setOrder)
+                .catch(console.error)
+                .finally(() => setLoading(false));
+        }
+    }, [orderId]);
+
+    useEffect(() => {
+        fetchOrderDetails();
+    }, [orderId, fetchOrderDetails]);
+
+    const handleModalSuccess = () => {
+        setIsModalOpen(false);
+        fetchOrderDetails(); // Refresh details after adding items
+    };
+
+    const handleSuccess = () => {
+        setIsModalOpen(false);
+        fetchOrderDetails(); // Generic success handler for all updates
+    };
+
+    if (loading) return <div>Loading order details...</div>;
+    if (!order) return <div>Order not found.</div>;
+
+    const totalPrice = order.order_items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
+
+    const getStatusColor = (status: string) => {
+        switch (status) {
+            case 'COMPLETED': return 'bg-green-100 text-green-800';
+            case 'CANCELED': return 'bg-red-100 text-red-800';
+            case 'CONFIRMED': return 'bg-yellow-100 text-yellow-800';
+            default: return 'bg-blue-100 text-blue-800';
+        }
+    }
+
+    return (
+        <div className="p-6">
+            <Link to="/admin/orders" className="text-blue-600 hover:underline mb-4 block">&larr; Back to All Orders</Link>
+
+            {orderId && <AddItemModal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} orderId={parseInt(orderId, 10)} onSuccess={handleModalSuccess} />}
+
+            <div className="flex justify-between items-start mb-6">
+                <div>
+                    <h1 className="text-3xl font-bold">Order #{order.id}</h1>
+                    <p className="text-gray-500">Placed on: {new Date(order.timestamp).toLocaleString()}</p>
+                </div>
+                <button onClick={() => setIsModalOpen(true)} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
+                    + Add Items
+                </button>
+            </div>
+
+            <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
+                {/* Order Items */}
+                <div className="md:col-span-2 bg-white p-6 rounded-lg shadow-md">
+                    <h2 className="text-xl font-semibold mb-4 border-b pb-2">Items</h2>
+                    <div className="space-y-3">
+                        {order.order_items.map(item => (
+                            <div key={item.id} className="flex justify-between items-center">
+                                <div>
+                                    <p className="font-semibold">{item.product_name} <span className="text-gray-500 font-normal">x {item.quantity}</span></p>
+                                    <p className="text-sm text-gray-600">@ ${item.price.toFixed(2)} each</p>
+                                </div>
+                                <p className="font-bold">${(item.price * item.quantity).toFixed(2)}</p>
+                            </div>
+                        ))}
+                    </div>
+                    <div className="mt-6 pt-4 border-t flex justify-end">
+                        <p className="text-lg font-bold">Total: ${totalPrice.toFixed(2)}</p>
+                    </div>
+                </div>
+
+                {/* Order Details */}
+                <div className="bg-white p-6 rounded-lg shadow-md">
+                    <h2 className="text-xl font-semibold mb-4 border-b pb-2">Details</h2>
+                    <div className="space-y-3">
+                        <p><strong>Status:</strong> <span className={`px-2 py-1 rounded-full text-sm font-semibold ${getStatusColor(order.status)}`}>{order.status.replace('_', ' ')}</span></p>
+                        <p><strong>Type:</strong> {order.type}</p>
+                        {order.type === 'TAB' && <p><strong>Table:</strong> {order.table_number}</p>}
+                        {order.front_staff_name && <p><strong>Staff:</strong> {order.front_staff_name}</p>}
+                        {order.type === 'ONLINE' && (
+                            <>
+                                <p><strong>Customer:</strong> {order.customer_name}</p>
+                                <p><strong>Address:</strong> {order.delivery_address}</p>
+                            </>
+                        )}
+                    </div>
+                </div>
+
+                <UpdateOrderStatusActions order={order} onSuccess={handleSuccess} />
+
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/OrdersPage.tsx
===================================================================
--- frontend/src/pages/OrdersPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/OrdersPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,94 @@
+// src/pages/OrdersPage.tsx
+import { useEffect, useState } from 'react';
+import type { OrderDto } from '../types/api';
+import { orderRepository } from '../api/orderRepository';
+import { Modal } from '../components/Modal';
+import { CreateTabOrderForm } from '../components/forms/CreateTabOrderForm';
+import { Link } from 'react-router-dom';
+
+export const OrdersPage = () => {
+    const [openOrders, setOpenOrders] = useState<OrderDto[]>([]);
+    const [loading, setLoading] = useState(true);
+    const [error, setError] = useState('');
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchOrders = async () => {
+        try {
+            setLoading(true);
+            const orders = await orderRepository.getOpenOrders();
+            setOpenOrders(orders);
+        } catch (err) {
+            setError('Failed to fetch open orders.');
+            console.error(err);
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    useEffect(() => {
+        fetchOrders();
+    }, []);
+
+    const handleFormSuccess = () => {
+        setIsModalOpen(false);
+        fetchOrders(); // Refresh the list after creating a new order
+    };
+
+    if (loading) return <div>Loading orders...</div>;
+    if (error) return <div className="text-red-500">{error}</div>;
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">Open Orders</h1>
+                <button
+                    onClick={() => setIsModalOpen(true)}
+                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
+                >
+                    + Create Tab
+                </button>
+            </div>
+
+            <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title="Create New Tab">
+                <CreateTabOrderForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            <div className="bg-white shadow-md rounded-lg overflow-hidden">
+                <table className="min-w-full leading-normal">
+                    <thead>
+                        <tr>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Order ID</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Type / Table</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Status</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Timestamp</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100"></th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {openOrders.map(order => (
+                            <tr key={order.id}>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">{order.id}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
+                                    {order.type === 'TAB' ? `Tab - Table ${order.table_number}` : 'Online'}
+                                </td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">
+                                    <span className="relative inline-block px-3 py-1 font-semibold text-green-900 leading-tight">
+                                        <span aria-hidden className="absolute inset-0 bg-green-200 opacity-50 rounded-full"></span>
+                                        <span className="relative">{order.status}</span>
+                                    </span>
+                                </td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">{new Date(order.timestamp).toLocaleString()}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm text-right">
+                                    {/* Update this button to a Link */}
+                                    <Link to={`/admin/orders/${order.id}`} className="text-indigo-600 hover:text-indigo-900 font-semibold">
+                                        View Details
+                                    </Link>
+                                </td>
+                            </tr>
+                        ))}
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/ProductsPage.tsx
===================================================================
--- frontend/src/pages/ProductsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/ProductsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,85 @@
+// src/pages/ProductsPage.tsx
+import { useEffect, useState } from 'react';
+import type { ProductDto } from '../types/api';
+import { productRepository } from '../api/productRepository';
+import { Modal } from '../components/Modal';
+import { CreateProductForm } from '../components/forms/CreateProductForm';
+
+export const ProductsPage = () => {
+    const [products, setProducts] = useState<ProductDto[]>([]);
+    const [loading, setLoading] = useState(true);
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchProducts = () => {
+        setLoading(true);
+        productRepository.getAllProducts()
+            .then(setProducts)
+            .catch(console.error)
+            .finally(() => setLoading(false));
+    };
+
+    useEffect(() => {
+        fetchProducts();
+    }, []);
+
+    const handleFormSuccess = () => {
+        setIsModalOpen(false);
+        fetchProducts();
+    };
+
+    const handleDelete = async (productId: number) => {
+        if (window.confirm('Are you sure you want to delete this product?')) {
+            try {
+                await productRepository.deleteProduct(productId);
+                fetchProducts();
+            } catch (error) {
+                alert('Failed to delete product.');
+            }
+        }
+    };
+
+    if (loading) return <div>Loading products...</div>;
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">Products</h1>
+                <button
+                    onClick={() => setIsModalOpen(true)}
+                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
+                >
+                    + Add Product
+                </button>
+            </div>
+
+            <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title="Create New Product">
+                <CreateProductForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            <div className="bg-white shadow-md rounded-lg overflow-hidden">
+                <table className="min-w-full leading-normal">
+                    <thead>
+                        <tr>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Product Name</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Category</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">Price</th>
+                            <th className="px-5 py-3 border-b-2 border-gray-200 bg-gray-100"></th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {products.map(prod => (
+                            <tr key={prod.id}>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">{prod.name}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">{prod.category.name}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm">${prod.price.toFixed(2)}</td>
+                                <td className="px-5 py-5 border-b border-gray-200 bg-white text-sm text-right">
+                                    <button onClick={() => handleDelete(prod.id)} className="text-red-600 hover:text-red-900">Delete</button>
+                                </td>
+                            </tr>
+                        ))}
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/ReservationsPage.tsx
===================================================================
--- frontend/src/pages/ReservationsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/ReservationsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,100 @@
+// src/pages/ReservationsPage.tsx
+import { useEffect, useState } from 'react';
+import type { ReservationDto } from '../types/api';
+import { reservationRepository } from '../api/reservationRepository';
+import { Modal } from '../components/Modal';
+import { AcceptReservationForm } from '../components/forms/AcceptReservationForm';
+import { CreateReservationForm } from '../components/forms/CreateReservationForm'; // Import the new form
+import { useAuth } from '../hooks/useAuth';
+
+export const ReservationsPage = () => {
+    const { user } = useAuth();
+    const [reservations, setReservations] = useState<ReservationDto[]>([]);
+    const [loading, setLoading] = useState(true);
+    const [selectedReservation, setSelectedReservation] = useState<ReservationDto | null>(null);
+    const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); // State for the creation modal
+
+    const fetchReservations = () => {
+        setLoading(true);
+        reservationRepository.getTodayReservations()
+            .then(data => setReservations(data))
+            .catch(console.error)
+            .finally(() => setLoading(false));
+    };
+
+    useEffect(() => {
+        fetchReservations();
+    }, []);
+
+    const handleOpenAcceptModal = (reservation: ReservationDto) => {
+        setSelectedReservation(reservation);
+    };
+
+    const handleCloseAcceptModal = () => {
+        setSelectedReservation(null);
+    };
+
+    const handleFormSuccess = () => {
+        // This function can now be used by both forms
+        handleCloseAcceptModal();
+        setIsCreateModalOpen(false);
+        fetchReservations(); // Refresh data
+    };
+
+    if (loading) return <div>Loading reservations...</div>;
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">Today's Reservations</h1>
+                <button
+                    onClick={() => setIsCreateModalOpen(true)}
+                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
+                >
+                    + Create Reservation
+                </button>
+            </div>
+
+            {/* Modal for creating a reservation */}
+            <Modal
+                isOpen={isCreateModalOpen}
+                onClose={() => setIsCreateModalOpen(false)}
+                title="Create New Reservation"
+            >
+                <CreateReservationForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            {/* Modal for accepting a reservation */}
+            {selectedReservation && (
+                <Modal
+                    isOpen={!!selectedReservation}
+                    onClose={handleCloseAcceptModal}
+                    title={`Accept Reservation for ${selectedReservation.email}`}
+                >
+                    <AcceptReservationForm
+                        reservationId={selectedReservation.id}
+                        onSuccess={handleFormSuccess}
+                    />
+                </Modal>
+            )}
+
+            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
+                {reservations.map(res => (
+                    <div key={res.id} className="bg-white p-4 rounded-lg shadow">
+                        <p className="font-bold">{res.email}</p>
+                        <p>Time: {new Date(res.datetime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</p>
+                        <p>Guests: {res.number_of_people}</p>
+                        {user?.user_type === "FRONT_STAFF" && <div className="mt-4">
+                            <button
+                                onClick={() => handleOpenAcceptModal(res)}
+                                className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-3 rounded text-sm"
+                            >
+                                Accept
+                            </button>
+                        </div>}
+                    </div>
+                ))}
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/ShiftsPage.tsx
===================================================================
--- frontend/src/pages/ShiftsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/ShiftsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,62 @@
+// src/pages/ShiftsPage.tsx
+import { useEffect, useState } from 'react';
+import type { ShiftDto } from '../types/api';
+import { shiftRepository } from '../api/shiftRepository';
+import { Modal } from '../components/Modal';
+import { CreateShiftForm } from '../components/forms/CreateShiftForm';
+
+export const ShiftsPage = () => {
+    const [shifts, setShifts] = useState<ShiftDto[]>([]);
+    const [loading, setLoading] = useState(true);
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchShifts = () => {
+        setLoading(true);
+        shiftRepository.getAllShifts()
+            .then(setShifts)
+            .catch(console.error)
+            .finally(() => setLoading(false));
+    };
+
+    useEffect(() => {
+        fetchShifts();
+    }, []);
+
+    const handleFormSuccess = () => {
+        setIsModalOpen(false);
+        fetchShifts();
+    };
+
+    if (loading) return <div>Loading shifts...</div>;
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">Shifts</h1>
+                <button
+                    onClick={() => setIsModalOpen(true)}
+                    className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
+                >
+                    + Create Shift
+                </button>
+            </div>
+
+            <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title="Create New Shift">
+                <CreateShiftForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            <div className="bg-white shadow-md rounded-lg p-4">
+                <h2 className="text-xl font-semibold mb-2">Scheduled Shifts</h2>
+                <ul>
+                    {shifts.map(shift => (
+                        <li key={shift.id} className="border-b py-2">
+                            Shift on <span className="font-semibold">{new Date(shift.date).toLocaleDateString()}</span> from{' '}
+                            <span className="font-semibold">{new Date(shift.start).toLocaleTimeString()}</span> to{' '}
+                            <span className="font-semibold">{new Date(shift.end).toLocaleTimeString()}</span>
+                        </li>
+                    ))}
+                </ul>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/pages/public/MenuPage.tsx
===================================================================
--- frontend/src/pages/public/MenuPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/public/MenuPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,129 @@
+// src/pages/public/MenuPage.tsx
+import { useEffect, useState } from 'react';
+import type { CategoryDto, ProductDto, CreateOrderDto, CreateOrderItemDto } from '../../types/api';
+import { categoryRepository } from '../../api/categoryRepository';
+import { productRepository } from '../../api/productRepository';
+import { orderRepository } from '../../api/orderRepository';
+import { CartSidebar } from '../../components/public/CartSidebar';
+import { Modal } from '../../components/Modal';
+import { useAuth } from '../../hooks/useAuth';
+import { useNavigate } from 'react-router-dom';
+import { CheckoutForm } from '../../components/public/CheckoutForm';
+
+interface CartItem extends ProductDto {
+    quantity: number;
+}
+
+export const MenuPage = () => {
+    const { isAuthenticated } = useAuth();
+    const navigate = useNavigate();
+    const [categories, setCategories] = useState<CategoryDto[]>([]);
+    const [products, setProducts] = useState<ProductDto[]>([]);
+    const [selectedCategoryId, setSelectedCategoryId] = useState<number | null>(null);
+    const [cart, setCart] = useState<Record<number, CartItem>>({});
+    const [isCheckoutModalOpen, setIsCheckoutModalOpen] = useState(false);
+    const [isSubmitting, setIsSubmitting] = useState(false);
+
+    useEffect(() => {
+        Promise.all([
+            categoryRepository.getAllCategories(),
+            productRepository.getAllProducts(),
+        ]).then(([catData, prodData]) => {
+            const availableCats = catData.filter(c => c.is_available);
+            setCategories(availableCats);
+            setProducts(prodData);
+            if (availableCats.length > 0) {
+                setSelectedCategoryId(availableCats[0].id);
+            }
+        }).catch(console.error);
+    }, []);
+
+    const updateCart = (product: ProductDto, change: 1 | -1) => {
+        setCart(prevCart => {
+            const existingItem = prevCart[product.id];
+            const newQuantity = (existingItem?.quantity || 0) + change;
+            if (newQuantity <= 0) {
+                const { [product.id]: _, ...rest } = prevCart;
+                return rest;
+            }
+            return { ...prevCart, [product.id]: { ...product, quantity: newQuantity } };
+        });
+    };
+
+    const handleCheckout = () => {
+        if (!isAuthenticated) {
+            alert("Please log in or register to place an order.");
+            navigate('/login');
+            return;
+        }
+        setIsCheckoutModalOpen(true);
+    };
+
+    const handleConfirmOrder = async (data: { delivery_address: string }) => {
+        setIsSubmitting(true);
+        const orderItems: CreateOrderItemDto[] = Object.values(cart).map(item => ({
+            product_id: item.id,
+            quantity: item.quantity,
+            price: item.price,
+            is_processed: false,
+        }));
+
+        const orderData: CreateOrderDto = {
+            order_items: orderItems,
+            status: "PENDING",
+            type: "ONLINE",
+            delivery_address: data.delivery_address,
+        };
+
+        try {
+            await orderRepository.createOnlineOrder(orderData);
+            alert("Order placed successfully!");
+            setCart({});
+            setIsCheckoutModalOpen(false);
+        } catch (error) {
+            alert("Failed to place order.");
+
+            console.error(error);
+        } finally {
+            setIsSubmitting(false);
+        }
+    };
+
+    const filteredProducts = products.filter(p => p.category.id === selectedCategoryId);
+
+    return (
+        <div className="flex flex-col md:flex-row p-4 gap-4 bg-gray-50 h-[calc(100vh-68px)]">
+            {/* Menu */}
+            <div className="flex-grow">
+                <div className="flex space-x-2 overflow-x-auto pb-2">
+                    {categories.map(cat => (
+                        <button key={cat.id} onClick={() => setSelectedCategoryId(cat.id)}
+                            className={`px-4 py-2 rounded-full font-semibold whitespace-nowrap ${selectedCategoryId === cat.id ? 'bg-blue-500 text-white' : 'bg-white'}`}>
+                            {cat.name}
+                        </button>
+                    ))}
+                </div>
+                <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-4">
+                    {filteredProducts.map(prod => (
+                        <div key={prod.id} className="bg-white p-4 rounded-lg shadow">
+                            <h4 className="font-bold">{prod.name}</h4>
+                            <p className="text-sm text-gray-500">{prod.description}</p>
+                            <div className="flex justify-between items-center mt-2">
+                                <span className="font-semibold">${prod.price.toFixed(2)}</span>
+                                <button onClick={() => updateCart(prod, 1)} className="bg-blue-100 text-blue-800 font-bold py-1 px-3 rounded">Add</button>
+                            </div>
+                        </div>
+                    ))}
+                </div>
+            </div>
+            {/* Cart */}
+            <div className="w-full md:w-80 lg:w-96 flex-shrink-0">
+                <CartSidebar cart={cart} onUpdateQuantity={updateCart} onCheckout={handleCheckout} />
+            </div>
+
+            <Modal isOpen={isCheckoutModalOpen} onClose={() => setIsCheckoutModalOpen(false)} title="Complete Your Order">
+                <CheckoutForm onSubmit={handleConfirmOrder} isSubmitting={isSubmitting} />
+            </Modal>
+        </div>
+    );
+};
Index: frontend/src/pages/public/MyOrdersPage.tsx
===================================================================
--- frontend/src/pages/public/MyOrdersPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/public/MyOrdersPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,67 @@
+// src/pages/public/MyOrdersPage.tsx
+import { useEffect, useState } from 'react';
+import type { OrderDto } from '../../types/api';
+import { orderRepository } from '../../api/orderRepository';
+import { useAuth } from '../../hooks/useAuth';
+
+const getStatusColor = (status: string) => {
+    switch (status) {
+        case 'COMPLETED': return 'bg-green-100 text-green-800';
+        case 'CANCELED': return 'bg-red-100 text-red-800';
+        case 'IN_PROGRESS': return 'bg-yellow-100 text-yellow-800';
+        default: return 'bg-blue-100 text-blue-800';
+    }
+};
+
+export const MyOrdersPage = () => {
+    const { user } = useAuth();
+    const [orders, setOrders] = useState<OrderDto[]>([]);
+    const [loading, setLoading] = useState(true);
+
+    useEffect(() => {
+        if (user) {
+            setLoading(true);
+            orderRepository.getOnlineOrdersByCustomer(user.id)
+                .then(setOrders)
+                .catch(console.error)
+                .finally(() => setLoading(false));
+        }
+    }, [user]);
+
+    if (loading) return <p className="p-6">Loading your orders...</p>;
+
+    return (
+        <div className="p-6 bg-gray-50 min-h-screen">
+            <h1 className="text-3xl font-bold mb-4">My Orders</h1>
+
+            {orders.length === 0 ? (
+                <p>You haven't placed any orders yet. Visit our menu to get started!</p>
+            ) : (
+                <div className="space-y-4">
+                    {orders.map(order => {
+                        const totalPrice = order.order_items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
+                        return (
+                            <div key={order.id} className="bg-white p-4 rounded-lg shadow-md">
+                                <div className="flex justify-between items-start">
+                                    <div>
+                                        <p className="font-bold text-lg">Order #{order.id}</p>
+                                        <p className="text-sm text-gray-500">
+                                            Placed on: {new Date(order.timestamp).toLocaleDateString()}
+                                        </p>
+                                    </div>
+                                    <span className={`px-2 py-1 rounded-full text-xs font-semibold ${getStatusColor(order.status)}`}>
+                                        {order.status.replace('_', ' ')}
+                                    </span>
+                                </div>
+                                <div className="mt-4 border-t pt-2">
+                                    <p><strong>Address:</strong> {order.delivery_address}</p>
+                                    <p><strong>Total:</strong> ${totalPrice.toFixed(2)}</p>
+                                </div>
+                            </div>
+                        );
+                    })}
+                </div>
+            )}
+        </div>
+    );
+};
Index: frontend/src/pages/public/MyReservationsPage.tsx
===================================================================
--- frontend/src/pages/public/MyReservationsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/public/MyReservationsPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,75 @@
+// src/pages/public/MyReservationsPage.tsx
+import { useEffect, useState } from 'react';
+import type { ReservationDto } from '../../types/api';
+import { reservationRepository } from '../../api/reservationRepository';
+import { Modal } from '../../components/Modal';
+import { CreateReservationForm } from '../../components/forms/CreateReservationForm';
+
+export const MyReservationsPage = () => {
+    const [reservations, setReservations] = useState<ReservationDto[]>([]);
+    const [loading, setLoading] = useState(true);
+    const [isModalOpen, setIsModalOpen] = useState(false);
+
+    const fetchReservations = () => {
+        setLoading(true);
+        reservationRepository.getMyReservations()
+            .then(setReservations)
+            .catch(console.error)
+            .finally(() => setLoading(false));
+    };
+
+    useEffect(() => {
+        fetchReservations();
+    }, []);
+
+    const handleCancel = async (id: number) => {
+        if (window.confirm("Are you sure you want to cancel this reservation?")) {
+            try {
+                await reservationRepository.deleteReservation(id);
+                alert("Reservation canceled.");
+                fetchReservations();
+            } catch (error) {
+                alert("Failed to cancel reservation.");
+            }
+        }
+    };
+
+    const handleFormSuccess = () => {
+        setIsModalOpen(false);
+        fetchReservations();
+    };
+
+    return (
+        <div className="p-6">
+            <div className="flex justify-between items-center mb-4">
+                <h1 className="text-3xl font-bold">My Reservations</h1>
+                <button onClick={() => setIsModalOpen(true)} className="bg-green-500 text-white font-bold py-2 px-4 rounded">
+                    + Make a Reservation
+                </button>
+            </div>
+
+            <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title="Make a New Reservation">
+                <CreateReservationForm onSuccess={handleFormSuccess} />
+            </Modal>
+
+            {loading ? <p>Loading...</p> : reservations.length === 0 ? (
+                <p>You have no upcoming reservations.</p>
+            ) : (
+                <div className="space-y-4">
+                    {reservations.map(res => (
+                        <div key={res.id} className="bg-white p-4 rounded-lg shadow-md flex justify-between items-center">
+                            <div>
+                                <p><strong>Date:</strong> {new Date(res.datetime).toLocaleDateString()}</p>
+                                <p><strong>Time:</strong> {new Date(res.datetime).toLocaleTimeString()}</p>
+                                <p><strong>Guests:</strong> {res.number_of_people}</p>
+                            </div>
+                            <button onClick={() => handleCancel(res.id)} className="bg-red-500 text-white font-bold py-1 px-3 rounded">
+                                Cancel
+                            </button>
+                        </div>
+                    ))}
+                </div>
+            )}
+        </div>
+    );
+};
Index: frontend/src/pages/public/RegisterPage.tsx
===================================================================
--- frontend/src/pages/public/RegisterPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/pages/public/RegisterPage.tsx	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,64 @@
+// src/pages/public/RegisterPage.tsx
+import { useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import { z } from 'zod';
+import { useNavigate } from 'react-router-dom';
+import { useAuth } from '../../hooks/useAuth';
+import { authRepository } from '../../api/authRepository';
+
+const registerSchema = z.object({
+    first_name: z.string().min(1, "First name is required"),
+    last_name: z.string().min(1, "Last name is required"),
+    email: z.string().email(),
+    password: z.string().min(6, "Password must be at least 6 characters"),
+    password_confirmation: z.string()
+}).refine(data => data.password === data.password_confirmation, {
+    message: "Passwords do not match",
+    path: ["password_confirmation"],
+});
+
+type RegisterFormData = z.infer<typeof registerSchema>;
+
+export const RegisterPage = () => {
+    const navigate = useNavigate();
+    const { login } = useAuth(); // We'll use this to log the user in after registration
+    const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<RegisterFormData>({
+        resolver: zodResolver(registerSchema),
+    });
+
+    const onSubmit = async (data: RegisterFormData) => {
+        try {
+            await authRepository.register(data);
+            // Automatically log in the user after successful registration
+            await login({ username: data.email, password: data.password });
+            navigate('/');
+        } catch (error) {
+            console.error(error);
+            alert('Registration failed. The email might already be in use.');
+        }
+    };
+
+    return (
+        <div className="min-h-screen flex items-center justify-center bg-gray-50">
+            <div className="bg-white p-8 rounded-lg shadow-md w-full max-w-md">
+                <h2 className="text-2xl font-bold mb-6 text-center">Create an Account</h2>
+                <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
+                    {/* Form fields for first_name, last_name, email, password, password_confirmation */}
+                    <input {...register('first_name')} placeholder="First Name" className="w-full p-2 border rounded" />
+                    {errors.first_name && <p className="text-red-500 text-xs">{errors.first_name.message}</p>}
+                    <input {...register('last_name')} placeholder="Last Name" className="w-full p-2 border rounded" />
+                    {errors.last_name && <p className="text-red-500 text-xs">{errors.last_name.message}</p>}
+                    <input {...register('email')} placeholder="Email" className="w-full p-2 border rounded" />
+                    {errors.email && <p className="text-red-500 text-xs">{errors.email.message}</p>}
+                    <input type="password" {...register('password')} placeholder="Password" className="w-full p-2 border rounded" />
+                    {errors.password && <p className="text-red-500 text-xs">{errors.password.message}</p>}
+                    <input type="password" {...register('password_confirmation')} placeholder="Confirm Password" className="w-full p-2 border rounded" />
+                    {errors.password_confirmation && <p className="text-red-500 text-xs">{errors.password_confirmation.message}</p>}
+                    <button type="submit" disabled={isSubmitting} className="w-full bg-blue-500 text-white p-3 rounded">
+                        {isSubmitting ? 'Registering...' : 'Register'}
+                    </button>
+                </form>
+            </div>
+        </div>
+    );
+};
Index: frontend/src/types/api.ts
===================================================================
--- frontend/src/types/api.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/types/api.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,191 @@
+// src/types/api.ts
+
+// Enum for user roles, centralizing the role definitions.
+export enum UserType {
+  CUSTOMER = "CUSTOMER",
+  MANAGER = "MANAGER",
+  FRONT_STAFF = "FRONT_STAFF",
+  BACK_STAFF = "BACK_STAFF",
+  USER = "USER",
+  EMPLOYEE = "EMPLOYEE",
+}
+
+// DTOs (Data Transfer Objects)
+
+export interface UserDto {
+  id: number;
+  email: string;
+  street?: string;
+  city?: string;
+  phone_number?: string;
+  user_type: UserType;
+}
+
+export interface AuthDto {
+  token: string;
+  user: UserDto;
+}
+
+export interface AuthRequest {
+  username?: string; // API docs say username, but likely email
+  password?: string;
+}
+
+export interface OrderItemDto {
+  id: number;
+  quantity: number;
+  price: number;
+  is_processed: boolean;
+  timestamp: string;
+  product_id: number;
+  product_name: string;
+}
+
+export interface OrderDto {
+  id: number;
+  timestamp: string;
+  status: string; // e.g., "PENDING", "IN_PROGRESS", "COMPLETED"
+  type: string; // "ONLINE" or "TAB"
+  customer_name?: string;
+  delivery_address?: string;
+  table_number?: number;
+  front_staff_name?: string;
+  order_items: OrderItemDto[];
+}
+
+export interface CreateOrderDto {
+  order_items: CreateOrderItemDto[];
+  status: string;
+  type: string;
+  delivery_address?: string;
+  table_number?: number;
+}
+
+export interface CreateOrderItemDto {
+  product_id: number;
+  quantity: number;
+  price: number;
+  is_processed: boolean;
+}
+
+export interface ReservationDto {
+  id: number;
+  stay_length: number;
+  datetime: string;
+  creation_timestamp: string;
+  number_of_people: number;
+  email: string; // Assuming user email
+}
+
+export interface CreateReservationDto {
+  stay_length: number;
+  datetime: string;
+  number_of_people: number;
+}
+
+export interface ShiftDto {
+  id: number;
+  date: string;
+  start: string;
+  end: string;
+}
+
+export interface AssignmentDto {
+  id: number;
+  clock_in_time?: string;
+  clock_out_time?: string;
+  manager: ManagerDto;
+  employee: EmployeeDto;
+  shift: ShiftDto;
+}
+
+export interface CreateAssignmentDto {
+  employee_id: number;
+  shift_id: number;
+}
+
+// src/types/api.ts (add these interfaces)
+
+export interface CreateShiftDto {
+  date: string; // "YYYY-MM-DD"
+  start: string; // "YYYY-MM-DDTHH:mm:ss"
+  end: string; // "YYYY-MM-DDTHH:mm:ss"
+}
+
+export interface CreateEmployeeRequest {
+  email: string;
+  password?: string;
+  street?: string;
+  city?: string;
+  phone_number?: string;
+  net_salary: number;
+  gross_salary: number;
+  employee_type: "MANAGER" | "FRONT_STAFF" | "BACK_STAFF";
+  staff_role_id?: number;
+  tip_percent?: number;
+}
+
+export interface EmployeeDto {
+  id: number;
+  email: string;
+  street: string;
+  city: string;
+  phone_number: string;
+  net_salary: number;
+  gross_salary: number;
+  user_type: UserType;
+}
+
+// src/types/api.ts (add these interfaces)
+
+export interface CategoryDto {
+  id: number;
+  name: string;
+  is_available: boolean;
+}
+
+export interface CreateCategoryDto {
+  name: string;
+  is_available: boolean;
+}
+
+export interface ProductDto {
+  id: number;
+  name: string;
+  price: number;
+  description: string;
+  category: CategoryDto;
+}
+
+export interface CreateProductDto {
+  name: string;
+  price: number;
+  description: string;
+  category_id: number;
+  tax_class: string; // e.g., "STANDARD", "REDUCED"
+  manage_inventory: boolean;
+  quantity?: number;
+  restock_level?: number;
+}
+
+export interface ShiftDto {
+  id: number;
+  date: string; // "YYYY-MM-DD"
+  start: string; // ISO DateTime string "YYYY-MM-DDTHH:mm:ss"
+  end: string; // ISO DateTime string "YYYY-MM-DDTHH:mm:ss"
+}
+
+export interface ManagerDto {
+  id: number;
+  email: string;
+}
+
+// src/types/api.ts (add this interface)
+
+export interface RegisterRequest {
+  email: string;
+  password?: string;
+  password_confirmation?: string;
+  first_name?: string;
+  last_name?: string;
+}
Index: frontend/src/utils/roles.ts
===================================================================
--- frontend/src/utils/roles.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/utils/roles.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,30 @@
+// src/utils/roles.ts
+import { UserType } from "../types/api";
+
+export const ROLES = {
+  MANAGER: UserType.MANAGER,
+  FRONT_STAFF: UserType.FRONT_STAFF,
+  BACK_STAFF: UserType.BACK_STAFF,
+  CUSTOMER: UserType.CUSTOMER,
+  USER: UserType.USER,
+  EMPLOYEE: UserType.EMPLOYEE,
+};
+
+// Define which pages each role can see in the navigation
+export const ROLE_PERMISSIONS: Record<UserType, string[]> = {
+  [UserType.MANAGER]: [
+    "/admin/orders",
+    "/admin/reservations",
+    "/admin/categories",
+    "/admin/products",
+    "/admin/shifts",
+    "/admin/employees",
+    "/admin/assignments",
+  ],
+  [UserType.FRONT_STAFF]: ["/admin/orders", "/admin/reservations"],
+  [UserType.BACK_STAFF]: ["/admin/orders"],
+  // Other roles are not part of the admin panel MVP
+  [UserType.CUSTOMER]: [],
+  [UserType.USER]: [],
+  [UserType.EMPLOYEE]: [],
+};
Index: frontend/src/vite-env.d.ts
===================================================================
--- frontend/src/vite-env.d.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/src/vite-env.d.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,1 @@
+/// <reference types="vite/client" />
Index: frontend/tsconfig.app.json
===================================================================
--- frontend/tsconfig.app.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/tsconfig.app.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,27 @@
+{
+  "compilerOptions": {
+    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+    "target": "ES2022",
+    "useDefineForClassFields": true,
+    "lib": ["ES2022", "DOM", "DOM.Iterable"],
+    "module": "ESNext",
+    "skipLibCheck": true,
+
+    /* Bundler mode */
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "verbatimModuleSyntax": true,
+    "moduleDetection": "force",
+    "noEmit": true,
+    "jsx": "react-jsx",
+
+    /* Linting */
+    "strict": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "erasableSyntaxOnly": true,
+    "noFallthroughCasesInSwitch": true,
+    "noUncheckedSideEffectImports": true
+  },
+  "include": ["src"]
+}
Index: frontend/tsconfig.json
===================================================================
--- frontend/tsconfig.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/tsconfig.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,7 @@
+{
+  "files": [],
+  "references": [
+    { "path": "./tsconfig.app.json" },
+    { "path": "./tsconfig.node.json" }
+  ]
+}
Index: frontend/tsconfig.node.json
===================================================================
--- frontend/tsconfig.node.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/tsconfig.node.json	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,25 @@
+{
+  "compilerOptions": {
+    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+    "target": "ES2023",
+    "lib": ["ES2023"],
+    "module": "ESNext",
+    "skipLibCheck": true,
+
+    /* Bundler mode */
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "verbatimModuleSyntax": true,
+    "moduleDetection": "force",
+    "noEmit": true,
+
+    /* Linting */
+    "strict": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "erasableSyntaxOnly": true,
+    "noFallthroughCasesInSwitch": true,
+    "noUncheckedSideEffectImports": true
+  },
+  "include": ["vite.config.ts"]
+}
Index: frontend/vite.config.ts
===================================================================
--- frontend/vite.config.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
+++ frontend/vite.config.ts	(revision 2a99fe90dafc1b06403172fdd3ce230af8c5d345)
@@ -0,0 +1,8 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+import tailwindcss from "@tailwindcss/vite";
+
+// https://vite.dev/config/
+export default defineConfig({
+  plugins: [react(), tailwindcss()],
+});
Index: nw
===================================================================
--- mvnw	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,259 +1,0 @@
-#!/bin/sh
-# ----------------------------------------------------------------------------
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-# ----------------------------------------------------------------------------
-
-# ----------------------------------------------------------------------------
-# Apache Maven Wrapper startup batch script, version 3.3.2
-#
-# Optional ENV vars
-# -----------------
-#   JAVA_HOME - location of a JDK home dir, required when download maven via java source
-#   MVNW_REPOURL - repo url base for downloading maven distribution
-#   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
-#   MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
-# ----------------------------------------------------------------------------
-
-set -euf
-[ "${MVNW_VERBOSE-}" != debug ] || set -x
-
-# OS specific support.
-native_path() { printf %s\\n "$1"; }
-case "$(uname)" in
-CYGWIN* | MINGW*)
-  [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
-  native_path() { cygpath --path --windows "$1"; }
-  ;;
-esac
-
-# set JAVACMD and JAVACCMD
-set_java_home() {
-  # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
-  if [ -n "${JAVA_HOME-}" ]; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ]; then
-      # IBM's JDK on AIX uses strange locations for the executables
-      JAVACMD="$JAVA_HOME/jre/sh/java"
-      JAVACCMD="$JAVA_HOME/jre/sh/javac"
-    else
-      JAVACMD="$JAVA_HOME/bin/java"
-      JAVACCMD="$JAVA_HOME/bin/javac"
-
-      if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
-        echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
-        echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
-        return 1
-      fi
-    fi
-  else
-    JAVACMD="$(
-      'set' +e
-      'unset' -f command 2>/dev/null
-      'command' -v java
-    )" || :
-    JAVACCMD="$(
-      'set' +e
-      'unset' -f command 2>/dev/null
-      'command' -v javac
-    )" || :
-
-    if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
-      echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
-      return 1
-    fi
-  fi
-}
-
-# hash string like Java String::hashCode
-hash_string() {
-  str="${1:-}" h=0
-  while [ -n "$str" ]; do
-    char="${str%"${str#?}"}"
-    h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
-    str="${str#?}"
-  done
-  printf %x\\n $h
-}
-
-verbose() { :; }
-[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
-
-die() {
-  printf %s\\n "$1" >&2
-  exit 1
-}
-
-trim() {
-  # MWRAPPER-139:
-  #   Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
-  #   Needed for removing poorly interpreted newline sequences when running in more
-  #   exotic environments such as mingw bash on Windows.
-  printf "%s" "${1}" | tr -d '[:space:]'
-}
-
-# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
-while IFS="=" read -r key value; do
-  case "${key-}" in
-  distributionUrl) distributionUrl=$(trim "${value-}") ;;
-  distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
-  esac
-done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
-[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
-
-case "${distributionUrl##*/}" in
-maven-mvnd-*bin.*)
-  MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
-  case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
-  *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
-  :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
-  :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
-  :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
-  *)
-    echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
-    distributionPlatform=linux-amd64
-    ;;
-  esac
-  distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
-  ;;
-maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
-*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
-esac
-
-# apply MVNW_REPOURL and calculate MAVEN_HOME
-# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
-[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
-distributionUrlName="${distributionUrl##*/}"
-distributionUrlNameMain="${distributionUrlName%.*}"
-distributionUrlNameMain="${distributionUrlNameMain%-bin}"
-MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
-MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
-
-exec_maven() {
-  unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
-  exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
-}
-
-if [ -d "$MAVEN_HOME" ]; then
-  verbose "found existing MAVEN_HOME at $MAVEN_HOME"
-  exec_maven "$@"
-fi
-
-case "${distributionUrl-}" in
-*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
-*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
-esac
-
-# prepare tmp dir
-if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
-  clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
-  trap clean HUP INT TERM EXIT
-else
-  die "cannot create temp dir"
-fi
-
-mkdir -p -- "${MAVEN_HOME%/*}"
-
-# Download and Install Apache Maven
-verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
-verbose "Downloading from: $distributionUrl"
-verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
-
-# select .zip or .tar.gz
-if ! command -v unzip >/dev/null; then
-  distributionUrl="${distributionUrl%.zip}.tar.gz"
-  distributionUrlName="${distributionUrl##*/}"
-fi
-
-# verbose opt
-__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
-[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
-
-# normalize http auth
-case "${MVNW_PASSWORD:+has-password}" in
-'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
-has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
-esac
-
-if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
-  verbose "Found wget ... using wget"
-  wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
-elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
-  verbose "Found curl ... using curl"
-  curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
-elif set_java_home; then
-  verbose "Falling back to use Java to download"
-  javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
-  targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
-  cat >"$javaSource" <<-END
-	public class Downloader extends java.net.Authenticator
-	{
-	  protected java.net.PasswordAuthentication getPasswordAuthentication()
-	  {
-	    return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
-	  }
-	  public static void main( String[] args ) throws Exception
-	  {
-	    setDefault( new Downloader() );
-	    java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
-	  }
-	}
-	END
-  # For Cygwin/MinGW, switch paths to Windows format before running javac and java
-  verbose " - Compiling Downloader.java ..."
-  "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
-  verbose " - Running Downloader.java ..."
-  "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
-fi
-
-# If specified, validate the SHA-256 sum of the Maven distribution zip file
-if [ -n "${distributionSha256Sum-}" ]; then
-  distributionSha256Result=false
-  if [ "$MVN_CMD" = mvnd.sh ]; then
-    echo "Checksum validation is not supported for maven-mvnd." >&2
-    echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
-    exit 1
-  elif command -v sha256sum >/dev/null; then
-    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
-      distributionSha256Result=true
-    fi
-  elif command -v shasum >/dev/null; then
-    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
-      distributionSha256Result=true
-    fi
-  else
-    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
-    echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
-    exit 1
-  fi
-  if [ $distributionSha256Result = false ]; then
-    echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
-    echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
-    exit 1
-  fi
-fi
-
-# unzip and move
-if command -v unzip >/dev/null; then
-  unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
-else
-  tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
-fi
-printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
-mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
-
-clean || :
-exec_maven "$@"
Index: nw.cmd
===================================================================
--- mvnw.cmd	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,149 +1,0 @@
-<# : batch portion
-@REM ----------------------------------------------------------------------------
-@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements.  See the NOTICE file
-@REM distributed with this work for additional information
-@REM regarding copyright ownership.  The ASF licenses this file
-@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
-@REM with the License.  You may obtain a copy of the License at
-@REM
-@REM    http://www.apache.org/licenses/LICENSE-2.0
-@REM
-@REM Unless required by applicable law or agreed to in writing,
-@REM software distributed under the License is distributed on an
-@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-@REM KIND, either express or implied.  See the License for the
-@REM specific language governing permissions and limitations
-@REM under the License.
-@REM ----------------------------------------------------------------------------
-
-@REM ----------------------------------------------------------------------------
-@REM Apache Maven Wrapper startup batch script, version 3.3.2
-@REM
-@REM Optional ENV vars
-@REM   MVNW_REPOURL - repo url base for downloading maven distribution
-@REM   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
-@REM   MVNW_VERBOSE - true: enable verbose log; others: silence the output
-@REM ----------------------------------------------------------------------------
-
-@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
-@SET __MVNW_CMD__=
-@SET __MVNW_ERROR__=
-@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
-@SET PSModulePath=
-@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
-  IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
-)
-@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
-@SET __MVNW_PSMODULEP_SAVE=
-@SET __MVNW_ARG0_NAME__=
-@SET MVNW_USERNAME=
-@SET MVNW_PASSWORD=
-@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
-@echo Cannot start maven from wrapper >&2 && exit /b 1
-@GOTO :EOF
-: end batch / begin powershell #>
-
-$ErrorActionPreference = "Stop"
-if ($env:MVNW_VERBOSE -eq "true") {
-  $VerbosePreference = "Continue"
-}
-
-# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
-$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
-if (!$distributionUrl) {
-  Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
-}
-
-switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
-  "maven-mvnd-*" {
-    $USE_MVND = $true
-    $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
-    $MVN_CMD = "mvnd.cmd"
-    break
-  }
-  default {
-    $USE_MVND = $false
-    $MVN_CMD = $script -replace '^mvnw','mvn'
-    break
-  }
-}
-
-# apply MVNW_REPOURL and calculate MAVEN_HOME
-# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
-if ($env:MVNW_REPOURL) {
-  $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
-  $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
-}
-$distributionUrlName = $distributionUrl -replace '^.*/',''
-$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
-$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
-if ($env:MAVEN_USER_HOME) {
-  $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
-}
-$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
-$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
-
-if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
-  Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
-  Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
-  exit $?
-}
-
-if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
-  Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
-}
-
-# prepare tmp dir
-$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
-$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
-$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
-trap {
-  if ($TMP_DOWNLOAD_DIR.Exists) {
-    try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
-    catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
-  }
-}
-
-New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
-
-# Download and Install Apache Maven
-Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
-Write-Verbose "Downloading from: $distributionUrl"
-Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
-
-$webclient = New-Object System.Net.WebClient
-if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
-  $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
-}
-[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
-$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
-
-# If specified, validate the SHA-256 sum of the Maven distribution zip file
-$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
-if ($distributionSha256Sum) {
-  if ($USE_MVND) {
-    Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
-  }
-  Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
-  if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
-    Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
-  }
-}
-
-# unzip and move
-Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
-Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
-try {
-  Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
-} catch {
-  if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
-    Write-Error "fail to move MAVEN_HOME"
-  }
-} finally {
-  try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
-  catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
-}
-
-Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
Index: m.xml
===================================================================
--- pom.xml	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,140 +1,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.5.3</version>
-        <relativePath/> <!-- lookup parent from repository -->
-    </parent>
-
-    <groupId>finki.db</groupId>
-    <artifactId>Tasty_Tabs</artifactId>
-    <version>0.0.1-SNAPSHOT</version>
-    <name>Tasty Tabs</name>
-    <description>Tasty Tabs</description>
-
-    <properties>
-        <java.version>17</java.version>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-jdbc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-jpa</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-security</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.flywaydb</groupId>
-            <artifactId>flyway-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.flywaydb</groupId>
-            <artifactId>flyway-database-postgresql</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-devtools</artifactId>
-            <scope>runtime</scope>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.postgresql</groupId>
-            <artifactId>postgresql</artifactId>
-            <scope>runtime</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- ✅ Fixed Lombok dependency -->
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>1.18.34</version>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
-            <version>2.3.0</version>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.datatype</groupId>
-            <artifactId>jackson-datatype-jsr310</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.jsonwebtoken</groupId>
-            <artifactId>jjwt-api</artifactId>
-            <version>0.11.2</version>
-        </dependency>
-        <dependency>
-            <groupId>io.jsonwebtoken</groupId>
-            <artifactId>jjwt-impl</artifactId>
-            <version>0.11.2</version>
-            <scope>runtime</scope>
-        </dependency>
-        <dependency>
-            <groupId>io.jsonwebtoken</groupId>
-            <artifactId>jjwt-jackson</artifactId>
-            <version>0.11.2</version>
-            <scope>runtime</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <!-- ✅ Added version and ensured Lombok is included in annotation processing -->
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.11.0</version>
-                <configuration>
-                    <annotationProcessorPaths>
-                        <path>
-                            <groupId>org.springframework.boot</groupId>
-                            <artifactId>spring-boot-configuration-processor</artifactId>
-                        </path>
-                        <path>
-                            <groupId>org.projectlombok</groupId>
-                            <artifactId>lombok</artifactId>
-                            <version>1.18.34</version>
-                        </path>
-                    </annotationProcessorPaths>
-                </configuration>
-            </plugin>
-
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
Index: c/main/java/finki/db/tasty_tabs/TastyTabsApplication.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/TastyTabsApplication.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class TastyTabsApplication {
-
-    public static void main(String[] args) {
-        SpringApplication.run(TastyTabsApplication.class, args);
-    }
-
-}
Index: c/main/java/finki/db/tasty_tabs/config/OpenApiConfig.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/config/OpenApiConfig.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,50 +1,0 @@
-package finki.db.tasty_tabs.config;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.PropertyNamingStrategies;
-import io.swagger.v3.core.jackson.ModelResolver;
-import io.swagger.v3.oas.models.Components;
-import io.swagger.v3.oas.models.OpenAPI;
-import io.swagger.v3.oas.models.media.StringSchema;
-import io.swagger.v3.oas.models.parameters.Parameter;
-import io.swagger.v3.oas.models.security.SecurityRequirement;
-import io.swagger.v3.oas.models.security.SecurityScheme;
-import io.swagger.v3.oas.models.servers.Server;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import org.springdoc.core.customizers.OpenApiCustomizer;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.List;
-
-@Configuration
-public class OpenApiConfig {
-
-    @Bean
-    public ModelResolver modelResolver(ObjectMapper objectMapper) {
-        return new ModelResolver(objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE));
-    }
-
-    @Bean
-    public OpenApiCustomizer globalHeaderCustomizer() {
-        return openApi -> {
-            // No action is performed here, effectively removing the global parameter
-        };
-    }
-
-    @Bean
-    public OpenAPI customOpenAPI() {
-        return new OpenAPI()
-                .components(new Components()
-                        .addSecuritySchemes("bearerAuth",
-                                new SecurityScheme()
-                                        .type(SecurityScheme.Type.HTTP)
-                                        .scheme("bearer")
-                                        .bearerFormat("JWT")
-                        )
-                )
-                .addSecurityItem(new SecurityRequirement().addList("bearerAuth"))
-                .addServersItem(new Server().url("http://localhost:8080").description("Local server"));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/config/WebConfig.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/config/WebConfig.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,22 +1,0 @@
-package finki.db.tasty_tabs.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class WebConfig implements WebMvcConfigurer {
-
-    public WebConfig() {
-    }
-
-    @Override
-    public void addCorsMappings(CorsRegistry registry) {
-        registry.addMapping("/**")
-                .allowedOrigins("*")
-                .allowedMethods("*")
-                .allowedHeaders("*")
-                .allowCredentials(false)
-                .maxAge(3600);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Assignment.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Assignment.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,104 +1,0 @@
-package finki.db.tasty_tabs.entity;
-
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * Entity: Assignment
- * Description: Represents shift assignment for each employee.
- */
-@Entity
-@Table(name = "assignments")
-@Data
-@NoArgsConstructor
-public class Assignment {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "clock_in_time")
-    private LocalDateTime clockInTime;
-
-    @Column(name = "clock_out_time")
-    private LocalDateTime clockOutTime;
-
-    @ManyToOne
-    @JoinColumn(name = "manager_id", referencedColumnName = "employee_id", nullable = false)
-    private Manager manager;
-
-    @ManyToOne
-    @JoinColumn(name = "employee_id", referencedColumnName = "user_id", nullable = false)
-    private Employee employee;
-
-    @ManyToOne
-    @JoinColumn(name = "shift_id", referencedColumnName = "id", nullable = false)
-    private Shift shift;
-
-    public Assignment(LocalDateTime clockInTime, LocalDateTime clockOutTime, Employee employee, Shift shift) {
-        this.clockInTime = clockInTime;
-        this.clockOutTime = clockOutTime;
-        this.employee = employee;
-        this.shift = shift;
-    }
-
-    public Assignment(LocalDateTime clockInTime, LocalDateTime clockOutTime, Manager manager, Employee employee, Shift shift) {
-        this.clockInTime = clockInTime;
-        this.clockOutTime = clockOutTime;
-        this.manager = manager;
-        this.employee = employee;
-        this.shift = shift;
-    }
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public LocalDateTime getClockInTime() {
-        return clockInTime;
-    }
-
-    public void setClockInTime(LocalDateTime clockInTime) {
-        this.clockInTime = clockInTime;
-    }
-
-    public LocalDateTime getClockOutTime() {
-        return clockOutTime;
-    }
-
-    public void setClockOutTime(LocalDateTime clockOutTime) {
-        this.clockOutTime = clockOutTime;
-    }
-
-    public Manager getManager() {
-        return manager;
-    }
-
-    public void setManager(Manager manager) {
-        this.manager = manager;
-    }
-
-    public Employee getEmployee() {
-        return employee;
-    }
-
-    public void setEmployee(Employee employee) {
-        this.employee = employee;
-    }
-
-    public Shift getShift() {
-        return shift;
-    }
-
-    public void setShift(Shift shift) {
-        this.shift = shift;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/BackStaff.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/BackStaff.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,20 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-/**
- * Entity: BackStaff
- * Description: A disjoint specialization of the Employee entity for back-office staff members.
- */
-@Entity
-@Table(name = "back_staff")
-@Data
-@NoArgsConstructor
-@PrimaryKeyJoinColumn(name = "employee_id")
-public class BackStaff extends Employee {
-
-    @ManyToOne
-    @JoinColumn(name = "staff_role_id", referencedColumnName = "id")
-    private StaffRole staffRole;
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Category.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Category.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package finki.db.tasty_tabs.entity;
-
-import com.fasterxml.jackson.annotation.JsonManagedReference;
-import jakarta.persistence.*;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: Category
- */
-@Entity
-@Table(name = "categories")
-@Data
-@NoArgsConstructor
-public class Category {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(nullable = false, unique = true)
-    private String name;
-
-    @Column(name = "is_available")
-    private Boolean isAvailable;
-
-    @OneToMany(mappedBy = "category", fetch = FetchType.LAZY)
-    @JsonManagedReference
-    private List<Product> products;
-
-    public Category(String name, Boolean isAvailable) {
-        this.name = name;
-        this.isAvailable = isAvailable;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Customer.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Customer.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,23 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: Customer
- * Description: Represents customers in the system. Inherits from User.
- */
-@Entity
-@Table(name = "customers")
-@Data
-@NoArgsConstructor
-@PrimaryKeyJoinColumn(name = "user_id") // Links to the User table
-public class Customer extends User {
-    
-    // Relationship for online orders placed by this customer
-    @OneToMany(mappedBy = "customer")
-    private List<OnlineOrder> onlineOrders;
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Employee.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Employee.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,66 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: Employee
- * Description: Represents employees of the system. Inherits from User.
- */
-@Entity
-@Table(name = "employees")
-@Data
-@PrimaryKeyJoinColumn(name = "user_id") // Links to the User table
-public class Employee extends User {
-
-    @Column(name = "net_salary", nullable = false)
-    private Double netSalary;
-
-    @Column(name = "gross_salary", nullable = false)
-    private Double grossSalary;
-
-    // Relationship for assignments given to this employee
-    @OneToMany(mappedBy = "employee")
-    private List<Assignment> assignments;
-
-    public Employee() {
-    }
-    public Employee(Double netSalary, Double grossSalary) {
-        this.netSalary = netSalary;
-        this.grossSalary = grossSalary;
-    }
-
-    public Employee(Long id, String email, String street, String city, String phoneNumber, Double netSalary, Double grossSalary, List<Assignment> assignments) {
-        super(id, email, street, city, phoneNumber);
-        this.netSalary = netSalary;
-        this.grossSalary = grossSalary;
-        this.assignments = assignments;
-    }
-
-    public Double getNetSalary() {
-        return netSalary;
-    }
-
-    public List<Assignment> getAssignments() {
-        return assignments;
-    }
-
-    public void setAssignments(List<Assignment> assignments) {
-        this.assignments = assignments;
-    }
-
-    public void setNetSalary(Double netSalary) {
-        this.netSalary = netSalary;
-    }
-
-    public Double getGrossSalary() {
-        return grossSalary;
-    }
-
-    public void setGrossSalary(Double grossSalary) {
-        this.grossSalary = grossSalary;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/EmployeeType.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/EmployeeType.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,5 +1,0 @@
-package finki.db.tasty_tabs.entity;
-
-public enum EmployeeType {
-    MANAGER, FRONT_STAFF, BACK_STAFF
-}
Index: c/main/java/finki/db/tasty_tabs/entity/FrontStaff.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/FrontStaff.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,65 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: FrontStaff
- * Description: A disjoint specialization of the Employee entity for front-facing staff members.
- */
-@Entity
-@Table(name = "front_staff")
-@Data
-@NoArgsConstructor
-@PrimaryKeyJoinColumn(name = "employee_id")
-public class FrontStaff extends Employee {
-
-    @Column(name = "tip_percent")
-    private Double tipPercent;
-
-    @ManyToOne
-    @JoinColumn(name = "staff_role_id", referencedColumnName = "id")
-    private StaffRole staffRole;
-
-    // Relationship for tab orders handled by this front staff member
-    @OneToMany(mappedBy = "frontStaff")
-    private List<TabOrder> tabOrders;
-
-    @OneToMany(mappedBy = "frontStaff")
-    private List<ReservationManagedFrontStaff> managedReservations;
-
-    public Double getTipPercent() {
-        return tipPercent;
-    }
-
-    public void setTipPercent(Double tipPercent) {
-        this.tipPercent = tipPercent;
-    }
-
-    public StaffRole getStaffRole() {
-        return staffRole;
-    }
-
-    public void setStaffRole(StaffRole staffRole) {
-        this.staffRole = staffRole;
-    }
-
-    public List<TabOrder> getTabOrders() {
-        return tabOrders;
-    }
-
-    public void setTabOrders(List<TabOrder> tabOrders) {
-        this.tabOrders = tabOrders;
-    }
-
-    public List<ReservationManagedFrontStaff> getManagedReservations() {
-        return managedReservations;
-    }
-
-    public void setManagedReservations(List<ReservationManagedFrontStaff> managedReservations) {
-        this.managedReservations = managedReservations;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Inventory.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Inventory.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,69 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-/**
- * Entity: Inventory
- * Description: Tracks product quantities and restocking levels.
- */
-@Entity
-@Table(name = "inventories")
-@Data
-@NoArgsConstructor
-public class Inventory {
-
-    @Id
-    @Column(name = "product_id")
-    private Long productId;
-
-    @OneToOne(fetch = FetchType.LAZY)
-    @MapsId
-    @JoinColumn(name = "product_id")
-    private Product product;
-
-    @Column(name = "quantity", nullable = false)
-    private Integer quantity;
-
-    @Column(name = "restock_level")
-    private Integer restockLevel;
-
-    public Inventory(Product product, Integer quantity, Integer restockLevel) {
-        this.product = product;  // @MapsId ќе го земе id-то
-        this.quantity = quantity;
-        this.restockLevel = restockLevel;
-    }
-
-
-    public Long getProductId() {
-        return productId;
-    }
-
-    public void setProductId(Long productId) {
-        this.productId = productId;
-    }
-
-    public Product getProduct() {
-        return product;
-    }
-
-    public void setProduct(Product product) {
-        this.product = product;
-    }
-
-    public Integer getQuantity() {
-        return quantity;
-    }
-
-    public void setQuantity(Integer quantity) {
-        this.quantity = quantity;
-    }
-
-    public Integer getRestockLevel() {
-        return restockLevel;
-    }
-
-    public void setRestockLevel(Integer restockLevel) {
-        this.restockLevel = restockLevel;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Manager.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Manager.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,28 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: Manager
- * Description: A disjoint specialization of the Employee entity for managers.
- */
-@Entity
-@Table(name = "managers")
-@Data
-@NoArgsConstructor
-@PrimaryKeyJoinColumn(name = "employee_id")
-public class Manager extends Employee {
-
-    // Relationship for shifts created by this manager
-    @OneToMany(mappedBy = "manager")
-    private List<Shift> createdShifts;
-
-    // Relationship for assignments created by this manager
-    @OneToMany(mappedBy = "manager")
-    private List<Assignment> createdAssignments;
-
-}
Index: c/main/java/finki/db/tasty_tabs/entity/OnlineOrder.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/OnlineOrder.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,39 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-/**
- * Entity: OnlineOrder
- * Description: Represents orders made online by customers.
- */
-@Entity
-@Table(name = "online_orders")
-@Data
-@NoArgsConstructor
-@PrimaryKeyJoinColumn(name = "order_id")
-public class OnlineOrder extends Order {
-
-    @ManyToOne
-    @JoinColumn(name = "customer_id", referencedColumnName = "user_id", nullable = false)
-    private Customer customer;
-
-    @Column(name = "delivery_address", nullable = false)
-    private String deliveryAddress;
-
-    public Customer getCustomer() {
-        return customer;
-    }
-
-    public void setCustomer(Customer customer) {
-        this.customer = customer;
-    }
-
-    public String getDeliveryAddress() {
-        return deliveryAddress;
-    }
-
-    public void setDeliveryAddress(String deliveryAddress) {
-        this.deliveryAddress = deliveryAddress;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Order.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Order.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,76 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-/**
- * Entity: Order
- * Description: Represents a customer's order in the system.
- */
-@Entity
-@Table(name = "orders") // "order" is a reserved keyword
-@Data
-@NoArgsConstructor
-@Inheritance(strategy = InheritanceType.JOINED)
-public class Order {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "datetime", nullable = false)
-    private LocalDateTime timestamp;
-
-    @Column(name = "status")
-    private String status;
-
-    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
-    private List<OrderItem> orderItems;
-
-    @OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
-    private Payment payment;
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public LocalDateTime getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(LocalDateTime timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public String getStatus() {
-        return status;
-    }
-
-    public void setStatus(String status) {
-        this.status = status;
-    }
-
-    public List<OrderItem> getOrderItems() {
-        return orderItems;
-    }
-
-    public void setOrderItems(List<OrderItem> orderItems) {
-        this.orderItems = orderItems;
-    }
-
-    public Payment getPayment() {
-        return payment;
-    }
-
-    public void setPayment(Payment payment) {
-        this.payment = payment;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/OrderItem.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/OrderItem.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,42 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * Entity: OrderItem
- * Description: Represents items in a customer's order.
- */
-@Entity
-@Table(name = "order_items")
-@Data
-@NoArgsConstructor
-public class OrderItem {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "quantity", nullable = false)
-    private Integer quantity;
-
-    @Column(name = "price", nullable = false)
-    private Double price;
-
-    @Column(name = "is_processed")
-    private Boolean isProcessed;
-
-    @Column(name = "created_at", nullable = false)
-    private LocalDateTime timestamp;
-
-    @ManyToOne
-    @JoinColumn(name = "product_id", referencedColumnName = "id", nullable = false)
-    private Product product;
-
-    @ManyToOne
-    @JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false)
-    private Order order;
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Payment.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Payment.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,87 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * Entity: Payment
- * Description: Represents payments for orders.
- */
-@Entity
-@Table(name = "payments")
-@Data
-@NoArgsConstructor
-public class Payment {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "tip_amount")
-    private Double tipAmount;
-
-    @Column(name = "created_at", nullable = false)
-    private LocalDateTime timestamp;
-
-    @Column(name = "payment_type", nullable = false)
-    private String paymentType;
-
-    @Column(name = "amount", nullable = false)
-    private Double amount;
-
-    @OneToOne
-    @JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false, unique = true)
-    private Order order;
-
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public Double getTipAmount() {
-        return tipAmount;
-    }
-
-    public void setTipAmount(Double tipAmount) {
-        this.tipAmount = tipAmount;
-    }
-
-    public LocalDateTime getTimestamp() {
-        return timestamp;
-    }
-
-    public void setTimestamp(LocalDateTime timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    public String getPaymentType() {
-        return paymentType;
-    }
-
-    public void setPaymentType(String paymentType) {
-        this.paymentType = paymentType;
-    }
-
-    public Double getAmount() {
-        return amount;
-    }
-
-    public void setAmount(Double amount) {
-        this.amount = amount;
-    }
-
-    public Order getOrder() {
-        return order;
-    }
-
-    public void setOrder(Order order) {
-        this.order = order;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Product.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Product.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,48 +1,0 @@
-package finki.db.tasty_tabs.entity;
-
-import com.fasterxml.jackson.annotation.JsonBackReference;
-import jakarta.persistence.*;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: Product
- */
-@Entity
-@Table(name = "products")
-@Data
-@NoArgsConstructor
-public class Product {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(nullable = false)
-    private String name;
-
-    @Column(nullable = false)
-    private Double price;
-
-    @Column(name = "tax_class")
-    private String taxClass;
-
-    @Column(length = 1024)
-    private String description;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "category_id", nullable = false)
-    @JsonBackReference
-    private Category category;
-
-    @Column(name = "manage_inventory")
-    private Boolean manageInventory;
-
-    @OneToOne(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
-    private Inventory inventory;
-
-    @OneToMany(mappedBy = "product")
-    private List<OrderItem> orderItems;
-}
Index: c/main/java/finki/db/tasty_tabs/entity/Reservation.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Reservation.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,98 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-/**
- * Entity: Reservation
- * Description: Represents reservations made by users.
- */
-@Entity
-@Table(name = "reservations")
-@Data
-@NoArgsConstructor
-public class Reservation {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "stay_length")
-    private Integer stayLength;
-
-    @Column(name = "datetime", nullable = false)
-    private LocalDateTime datetime;
-
-    @Column(name = "creation_timestamp", nullable = false)
-    private LocalDateTime creationTimestamp;
-
-    @Column(name = "number_of_people", nullable = false)
-    private Integer numberOfPeople;
-
-    @ManyToOne
-    @JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)
-    private User user;
-
-    @OneToMany(mappedBy = "reservation")
-    private List<ReservationManagedFrontStaff> managedReservations;
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public Integer getStayLength() {
-        return stayLength;
-    }
-
-    public void setStayLength(Integer stayLength) {
-        this.stayLength = stayLength;
-    }
-
-    public LocalDateTime getDatetime() {
-        return datetime;
-    }
-
-    public void setDatetime(LocalDateTime datetime) {
-        this.datetime = datetime;
-    }
-
-    public LocalDateTime getCreationTimestamp() {
-        return creationTimestamp;
-    }
-
-    public void setCreationTimestamp(LocalDateTime creationTimestamp) {
-        this.creationTimestamp = creationTimestamp;
-    }
-
-    public Integer getNumberOfPeople() {
-        return numberOfPeople;
-    }
-
-    public void setNumberOfPeople(Integer numberOfPeople) {
-        this.numberOfPeople = numberOfPeople;
-    }
-
-    public User getUser() {
-        return user;
-    }
-
-    public void setUser(User user) {
-        this.user = user;
-    }
-
-    public List<ReservationManagedFrontStaff> getManagedReservations() {
-        return managedReservations;
-    }
-
-    public void setManagedReservations(List<ReservationManagedFrontStaff> managedReservations) {
-        this.managedReservations = managedReservations;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/ReservationManagedFrontStaff.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/ReservationManagedFrontStaff.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,30 +1,0 @@
-package finki.db.tasty_tabs.entity;// finki.db.tasty_tabs.entity.ReservationManagedFrontStaff
-import jakarta.persistence.*;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import finki.db.tasty_tabs.entity.composite_keys.ReservationManagedFrontStaffId;
-
-@Entity
-@Table(name = "frontstaff_managed_reservations")
-@Data
-@NoArgsConstructor
-public class ReservationManagedFrontStaff {
-
-    @EmbeddedId
-    private ReservationManagedFrontStaffId id;
-
-    @ManyToOne
-    @MapsId("reservationId")
-    @JoinColumn(name = "reservation_id", referencedColumnName = "id")
-    private Reservation reservation;
-
-    @ManyToOne
-    @MapsId("frontstaffId")
-    @JoinColumn(name = "front_staff_id", referencedColumnName = "employee_id")
-    private FrontStaff frontStaff;
-
-    @ManyToOne
-    @MapsId("tableNumber")
-    @JoinColumn(name = "table_number", referencedColumnName = "table_number")
-    private RestaurantTable restaurantTable;
-}
Index: c/main/java/finki/db/tasty_tabs/entity/RestaurantTable.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/RestaurantTable.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,36 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: Table
- * Description: Represents dining tables in the system.
- */
-@Entity
-@Table(name = "tables") // "table" is a reserved keyword
-@Data
-@NoArgsConstructor
-public class RestaurantTable {
-
-    @Id
-    @Column(name = "table_number")
-    private Integer tableNumber;
-
-    @Column(name = "seat_capacity", nullable = false)
-    private Integer seatCapacity;
-
-    @OneToMany(mappedBy = "restaurantTable")
-    private List<TabOrder> tabOrders;
-
-    @OneToMany(mappedBy = "restaurantTable")
-    private List<ReservationManagedFrontStaff> managedReservations;
-
-    public RestaurantTable(Integer tableNumber, Integer seatCapacity) {
-        this.tableNumber=tableNumber;
-        this.seatCapacity=seatCapacity;
-    }
-}
-
Index: c/main/java/finki/db/tasty_tabs/entity/Shift.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/Shift.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,101 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-
-/**
- * Entity: Shift
- * Description: Represents a work shift in the system.
- */
-@Entity
-@Table(name = "shifts")
-@Data
-@NoArgsConstructor
-public class Shift {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "date", nullable = false)
-    private LocalDate date;
-
-    @Column(name = "start_time", nullable = false)
-    private LocalDateTime start;
-
-    @Column(name = "end_time", nullable = false)
-    private LocalDateTime end;
-
-    @ManyToOne
-    @JoinColumn(name = "manager_id", referencedColumnName = "employee_id", nullable = false)
-    private Manager manager;
-
-    @OneToMany(mappedBy = "shift")
-    private List<Assignment> assignments;
-
-    public Shift(LocalDate date, LocalDateTime start, LocalDateTime end, Manager manager) {
-        this.date = date;
-        this.start = start;
-        this.end = end;
-        this.manager = manager;
-    }
-
-    public Shift(LocalDate date, LocalDateTime start, LocalDateTime end) {
-        this.date = date;
-        this.start = start;
-        this.end = end;
-    }
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public LocalDate getDate() {
-        return date;
-    }
-
-    public void setDate(LocalDate date) {
-        this.date = date;
-    }
-
-    public LocalDateTime getStart() {
-        return start;
-    }
-
-    public void setStart(LocalDateTime start) {
-        this.start = start;
-    }
-
-    public LocalDateTime getEnd() {
-        return end;
-    }
-
-    public void setEnd(LocalDateTime end) {
-        this.end = end;
-    }
-
-    public Manager getManager() {
-        return manager;
-    }
-
-    public void setManager(Manager manager) {
-        this.manager = manager;
-    }
-
-    public List<Assignment> getAssignments() {
-        return assignments;
-    }
-
-    public void setAssignments(List<Assignment> assignments) {
-        this.assignments = assignments;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/StaffRole.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/StaffRole.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,31 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * Entity: StaffRole
- * Description: Defines roles for staff members.
- */
-@Entity
-@Table(name = "staff_roles")
-@Data
-@NoArgsConstructor
-public class StaffRole {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "name", nullable = false, unique = true)
-    private String name;
-
-    @OneToMany(mappedBy = "staffRole")
-    private List<FrontStaff> frontStaffs;
-
-    @OneToMany(mappedBy = "staffRole")
-    private List<BackStaff> backStaffs;
-}
Index: c/main/java/finki/db/tasty_tabs/entity/TabOrder.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/TabOrder.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,40 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-/**
- * Entity: TabOrder
- * Description: Represents orders made at a specific table.
- */
-@Entity
-@Table(name = "tab_orders")
-@Data
-@NoArgsConstructor
-@PrimaryKeyJoinColumn(name = "order_id")
-public class TabOrder extends Order {
-
-    @ManyToOne
-    @JoinColumn(name = "table_number", referencedColumnName = "table_number", nullable = false)
-    private RestaurantTable restaurantTable;
-
-    @ManyToOne
-    @JoinColumn(name = "front_staff_id", referencedColumnName = "employee_id", nullable = false)
-    private FrontStaff frontStaff;
-
-    public RestaurantTable getRestaurantTable() {
-        return restaurantTable;
-    }
-
-    public void setRestaurantTable(RestaurantTable restaurantTable) {
-        this.restaurantTable = restaurantTable;
-    }
-
-    public FrontStaff getFrontStaff() {
-        return frontStaff;
-    }
-
-    public void setFrontStaff(FrontStaff frontStaff) {
-        this.frontStaff = frontStaff;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/User.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/User.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,109 +1,0 @@
-package finki.db.tasty_tabs.entity;
-import jakarta.persistence.*;
-import jakarta.persistence.Table;
-import lombok.Data;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-import java.util.List;
-
-/**
- * Entity: User
- * Description: Contains main information about all users in the system.
- */
-@Entity
-@Table(name = "users") // "user" is often a reserved keyword in SQL
-@Data
-@Getter
-@Setter
-@NoArgsConstructor
-@Inheritance(strategy = InheritanceType.JOINED) // Strategy to allow for Employee/Customer subtypes
-public class User {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(name = "email", nullable = false, unique = true)
-    private String email;
-
-    @Column(name = "street")
-    private String street;
-
-    @Column(name = "city")
-    private String city;
-
-    @Column(name = "phone_number")
-    private String phoneNumber;
-
-    @Column(name = "password", nullable = false)
-    private String password;
-
-    // Relationship for Reservations made by a user (if they are a customer)
-    @OneToMany(mappedBy = "user")
-    private List<Reservation> reservations;
-    public User(Long id, String email, String street, String city, String phoneNumber) {
-        this.id = id;
-        this.email = email;
-        this.street = street;
-        this.city = city;
-        this.phoneNumber = phoneNumber;
-    }
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public String getEmail() {
-        return email;
-    }
-
-    public void setEmail(String email) {
-        this.email = email;
-    }
-
-    public String getStreet() {
-        return street;
-    }
-
-    public void setStreet(String street) {
-        this.street = street;
-    }
-
-    public String getCity() {
-        return city;
-    }
-
-    public void setCity(String city) {
-        this.city = city;
-    }
-
-    public String getPhoneNumber() {
-        return phoneNumber;
-    }
-
-    public void setPhoneNumber(String phoneNumber) {
-        this.phoneNumber = phoneNumber;
-    }
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public List<Reservation> getReservations() {
-        return reservations;
-    }
-
-    public void setReservations(List<Reservation> reservations) {
-        this.reservations = reservations;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/composite_keys/ReservationManagedFrontStaffId.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/composite_keys/ReservationManagedFrontStaffId.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package finki.db.tasty_tabs.entity.composite_keys;
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import java.io.Serializable;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import java.util.Objects;
-
-@Embeddable
-@Data
-@NoArgsConstructor
-public class ReservationManagedFrontStaffId implements Serializable {
-
-    @Column(name = "reservation_id")
-    private Long reservationId;
-
-    @Column(name = "front_staff_id")
-    private Long frontstaffId;
-
-    @Column(name = "table_number")
-    private Long tableNumber;
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        ReservationManagedFrontStaffId that = (ReservationManagedFrontStaffId) o;
-        return Objects.equals(reservationId, that.reservationId) &&
-                Objects.equals(frontstaffId, that.frontstaffId) &&
-                Objects.equals(tableNumber, that.tableNumber);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(reservationId, frontstaffId, tableNumber);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/AssignmentNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/AssignmentNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class AssignmentNotFoundException extends DomainException {
-
-    public AssignmentNotFoundException(Long id) {
-        super(String.format("Assignment with id %d doesnt exist",id));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/CategoryNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/CategoryNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class CategoryNotFoundException extends DomainException {
-
-    public CategoryNotFoundException(String name) {
-        super(String.format("Category: %s doesnt exist",name));
-    }
-    public CategoryNotFoundException() {
-        super("Category doesnt exist");
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/DomainException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/DomainException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public abstract class DomainException extends RuntimeException {
-    public DomainException(String message) {
-        super(message);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/EmployeeNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/EmployeeNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class EmployeeNotFoundException extends DomainException {
-
-    public EmployeeNotFoundException(Long id) {
-        super(String.format("Employee with id %d doesnt exist",id));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/FrontStaffNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/FrontStaffNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class FrontStaffNotFoundException extends DomainException {
-
-    public FrontStaffNotFoundException(Long id) {
-        super(String.format("FrontStaff with id %d doesnt exist",id));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/InvalidOrderTypeException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/InvalidOrderTypeException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class InvalidOrderTypeException extends DomainException {
-
-    public InvalidOrderTypeException(String message) {
-        super(message);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/OrderItemNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderItemNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class OrderItemNotFoundException extends DomainException {
-
-    public OrderItemNotFoundException() {
-        super(String.format("OrderItem doesnt exist"));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/OrderNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/OrderNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class OrderNotFoundException extends DomainException {
-
-    public OrderNotFoundException(Long id) {
-        super(String.format("Order with id %d doesnt exist",id));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/PaymentNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/PaymentNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class PaymentNotFoundException extends DomainException {
-
-    public PaymentNotFoundException(Long id) {
-        super(String.format("Payment with id %d doesnt exist",id));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class ProductNotFoundException extends DomainException {
-
-    public ProductNotFoundException(Long id) {
-        super(String.format("Product with id %d doesnt exist",id));
-    }
-}
-
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotInStockException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/ProductNotInStockException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class ProductNotInStockException extends DomainException {
-
-    public ProductNotInStockException(String name) {
-        super(String.format("Product: %s not in stock",name));
-    }
-}
-
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/ReservationNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/ReservationNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class ReservationNotFoundException extends DomainException {
-
-    public ReservationNotFoundException(Long id) {
-        super(String.format("Reservation with id %d doesnt exist",id));
-    }
-}
-
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/ShiftNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/ShiftNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class ShiftNotFoundException extends DomainException {
-
-    public ShiftNotFoundException(Long id) {
-        super(String.format("Shift with id %d doesnt exist",id));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/TableNotFoundException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNotFoundException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class TableNotFoundException extends DomainException {
-
-    public TableNotFoundException(Integer id) {
-        super(String.format("Table with id %d doesnt exist",id));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/entity/exceptions/TableNumberAlreadyExistsException.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/entity/exceptions/TableNumberAlreadyExistsException.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.entity.exceptions;
-
-public class TableNumberAlreadyExistsException extends DomainException {
-
-    public TableNumberAlreadyExistsException(Integer number) {
-        super(String.format("Table: %d already exists", number));
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/repository/AssignmentRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/AssignmentRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,10 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Assignment;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.Optional;
-
-public interface AssignmentRepository extends JpaRepository<Assignment, Long> {
-    Optional<Assignment> findByEmployeeIdAndShiftId(Long employeeId, Long shiftId);
-}
Index: c/main/java/finki/db/tasty_tabs/repository/BackStaffRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/BackStaffRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.BackStaff;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface BackStaffRepository extends JpaRepository<BackStaff, Long> {
-}
Index: c/main/java/finki/db/tasty_tabs/repository/CategoryRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/CategoryRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,44 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Category;
-import jakarta.transaction.Transactional;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-import java.util.Optional;
-
-@Repository
-public interface CategoryRepository extends JpaRepository<Category, Long> {
-
-    Optional<Category> findByName(String name);
-    @Query(value = "SELECT * FROM category WHERE id = :id", nativeQuery = true)
-    Category customFindCategoryById(@Param("id") Long id);
-
-    @Query(value = "SELECT * FROM category", nativeQuery = true)
-    List<Category> customFindAllCategories();
-
-    // Custom INSERT (note: JPA doesn't usually do INSERT via query, so avoid this if possible)
-    @Modifying
-    @Transactional
-    @Query(value = "INSERT INTO category (name, is_available) VALUES (:name, :isAvailable)", nativeQuery = true)
-    void customInsertCategory(@Param("name") String name, @Param("isAvailable") Boolean isAvailable);
-
-    @Modifying
-    @Transactional
-    @Query(value = "UPDATE category SET name = :name, is_available = :isAvailable WHERE id = :id", nativeQuery = true)
-    int customUpdateCategory(@Param("id") Long id,
-                       @Param("name") String name,
-                       @Param("isAvailable") Boolean isAvailable);
-
-    @Modifying
-    @Transactional
-    @Query(value = "DELETE FROM category WHERE id = :id", nativeQuery = true)
-    int customDeleteCategoryById(@Param("id") Long id);
-
-    @Query(value = "SELECT * FROM category WHERE name = :name", nativeQuery = true)
-    Category customFindCategoryByName(@Param("name") String name);
-}
Index: c/main/java/finki/db/tasty_tabs/repository/CustomerRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/CustomerRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Customer;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface CustomerRepository extends JpaRepository<Customer, Long> {}
Index: c/main/java/finki/db/tasty_tabs/repository/EmployeeRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/EmployeeRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Employee;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface EmployeeRepository extends JpaRepository<Employee, Long> {}
Index: c/main/java/finki/db/tasty_tabs/repository/FrontStaffRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/FrontStaffRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.FrontStaff;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface FrontStaffRepository extends JpaRepository<FrontStaff, Long> {}
Index: c/main/java/finki/db/tasty_tabs/repository/InventoryRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/InventoryRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Inventory;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface InventoryRepository extends JpaRepository<Inventory,Long> {
-}
Index: c/main/java/finki/db/tasty_tabs/repository/ManagerRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/ManagerRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,10 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Manager;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.Optional;
-
-public interface ManagerRepository extends JpaRepository<Manager, Long> {
-    Optional<Manager> findByEmail(String email);
-}
Index: c/main/java/finki/db/tasty_tabs/repository/OnlineOrderRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/OnlineOrderRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Customer;
-import finki.db.tasty_tabs.entity.OnlineOrder;
-import finki.db.tasty_tabs.entity.Order;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.List;
-
-public interface OnlineOrderRepository extends JpaRepository<OnlineOrder, Long> {
-
-    List<OnlineOrder> findAllByCustomer_Id(Long id);
-    List<OnlineOrder> findAllByStatus(String status);
-
-}
Index: c/main/java/finki/db/tasty_tabs/repository/OrderItemRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/OrderItemRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Order;
-import finki.db.tasty_tabs.entity.OrderItem;
-import finki.db.tasty_tabs.entity.Product;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.Optional;
-
-public interface OrderItemRepository extends JpaRepository<OrderItem, Long> {
-    Optional<OrderItem> findByOrderAndProduct(Order order, Product product);
-
-}
Index: c/main/java/finki/db/tasty_tabs/repository/OrderRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/OrderRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Order;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.List;
-
-public interface OrderRepository extends JpaRepository<Order, Long> {
-}
Index: c/main/java/finki/db/tasty_tabs/repository/PaymentRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/PaymentRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Payment;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import java.util.Optional;
-@Repository
-public interface PaymentRepository extends JpaRepository<Payment, Long> {
-    // Find a payment by its associated order ID
-    Optional<Payment> findByOrderId(Long orderId);
-}
Index: c/main/java/finki/db/tasty_tabs/repository/ProductRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/ProductRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Product;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-@Repository
-public interface ProductRepository extends JpaRepository<Product, Long> {
-    List<Product> findAllByName(String name);
-}
Index: c/main/java/finki/db/tasty_tabs/repository/ReservationManagedFrontStaffRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/ReservationManagedFrontStaffRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.ReservationManagedFrontStaff;
-import finki.db.tasty_tabs.entity.composite_keys.ReservationManagedFrontStaffId;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface ReservationManagedFrontStaffRepository extends JpaRepository<ReservationManagedFrontStaff, ReservationManagedFrontStaffId> { }
Index: c/main/java/finki/db/tasty_tabs/repository/ReservationRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/ReservationRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Reservation;
-import finki.db.tasty_tabs.entity.User;
-import org.springframework.data.jpa.repository.JpaRepository;
-import java.time.LocalDateTime;
-import java.util.List;
-
-public interface ReservationRepository extends JpaRepository<Reservation, Long> {
-    List<Reservation> findAllByUser(User user);
-    List<Reservation> findAllByDatetimeBetween(LocalDateTime start, LocalDateTime end);
-}
Index: c/main/java/finki/db/tasty_tabs/repository/RestaurantTableRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/RestaurantTableRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.RestaurantTable;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-@Repository
-public interface RestaurantTableRepository extends JpaRepository<RestaurantTable, Integer> {
-
-    List<RestaurantTable> findAllBySeatCapacity(Integer seatCapacity);
-}
Index: c/main/java/finki/db/tasty_tabs/repository/ShiftRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/ShiftRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.Shift;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface ShiftRepository extends JpaRepository<Shift, Long> {}
Index: c/main/java/finki/db/tasty_tabs/repository/StaffRoleRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/StaffRoleRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.StaffRole;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface StaffRoleRepository extends JpaRepository<StaffRole, Long> {} // Added
Index: c/main/java/finki/db/tasty_tabs/repository/TabOrderRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/TabOrderRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.OnlineOrder;
-import finki.db.tasty_tabs.entity.TabOrder;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-public interface TabOrderRepository extends JpaRepository<TabOrder, Long> {
-    List<TabOrder> findByRestaurantTable_TableNumberAndTimestampBetween(Integer tableNumber, LocalDateTime startOfDay, LocalDateTime endOfDay);
-    List<TabOrder> findAllByFrontStaffId(Long frontStaffId);
-    List<TabOrder> findAllByStatus(String status);
-
-}
Index: c/main/java/finki/db/tasty_tabs/repository/UserRepository.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/repository/UserRepository.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package finki.db.tasty_tabs.repository;
-
-import finki.db.tasty_tabs.entity.User;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.Optional;
-
-public interface UserRepository extends JpaRepository<User, Long> {
-    Optional<User> findByEmail(String email);
-
-    boolean existsByEmail(String email);
-}
Index: c/main/java/finki/db/tasty_tabs/service/AssignmentService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/AssignmentService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.Assignment;
-import finki.db.tasty_tabs.web.dto.CreateAssignmentDto;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-public interface AssignmentService {
-    List<Assignment> getAllAssignments();
-    Assignment getAssignmentById(Long id);
-    Assignment createAssignment(CreateAssignmentDto dto, String managerEmail);
-    Assignment updateAssignment(Long id, CreateAssignmentDto dto, String managerEmail);
-    void deleteAssignment(Long id, String managerEmail);
-    // New method for employee to clock in/out
-    Assignment clockInShift(Long assignmentId, String employeeEmail, LocalDateTime clockInTime);
-    Assignment clockOutShift(Long assignmentId, String employeeEmail, LocalDateTime clockOutTime);
-}
Index: c/main/java/finki/db/tasty_tabs/service/AuthService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/AuthService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.web.dto.AuthDto;
-import finki.db.tasty_tabs.web.dto.RegisterRequest;
-import finki.db.tasty_tabs.web.dto.UserDto;
-
-public interface AuthService {
-    AuthDto authenticate(String username, String password);
-    AuthDto register(RegisterRequest request);
-    UserDto getAuthenticatedUser();
-}
Index: c/main/java/finki/db/tasty_tabs/service/CategoryService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/CategoryService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.Category;
-
-import java.util.List;
-import java.util.Optional;
-
-public interface CategoryService {
-    Category findById(Long id);
-    List<Category> getAllCategories();
-    Category updateCategory(Long id,Category category);
-    void deleteCategory(Long id);
-    Category getCategoryByName(String name);
-    Category createCategory(Category category);
-}
Index: c/main/java/finki/db/tasty_tabs/service/EmployeeService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/EmployeeService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.Employee;
-import finki.db.tasty_tabs.web.dto.CreateEmployeeRequest;
-
-public interface EmployeeService { // New Service
-    Employee createEmployee(CreateEmployeeRequest request);
-}
Index: c/main/java/finki/db/tasty_tabs/service/OrderService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/OrderService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,46 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.*;
-import finki.db.tasty_tabs.web.dto.CreateOrderDto;
-import finki.db.tasty_tabs.web.dto.CreateOrderItemDto;
-
-import java.time.LocalDate;
-import java.util.List;
-
-public interface OrderService {
-    List<Order> findAll();
-    Order findById(Long id);
-
-    Order updateOrder(Long id, CreateOrderDto dto);
-    void deleteOrder(Long id);
-
-    double calculateTotalPrice(Long orderId);
-    void updateOrderStatus(Long orderId, String newStatus);
-
-    // Methods for Order Items
-    OrderItem addItemToOrder(Long orderId, CreateOrderItemDto itemDto);
-    void decreaseOrderItemQuantity(Long orderItemId);
-    OrderItem updateOrderItem(Long orderItemId, CreateOrderItemDto itemDto);
-    void deleteOrderItem(Long orderItemId);
-    OrderItem processOrderItem(Long orderItemId);
-
-    // Specific OnlineOrder methods
-    OnlineOrder createOnlineOrder(CreateOrderDto dto, String userEmail);
-    OnlineOrder findOnlineOrderById(Long id);
-    List<OnlineOrder> findAllOnlineOrders();
-    List<OnlineOrder> findOnlineOrdersByCustomer(Long customerId);
-
-    // Specific TabOrder methods
-    TabOrder createTabOrder(CreateOrderDto dto, String userEmail);
-    TabOrder findTabOrderById(Long id);
-    List<TabOrder> findAllTabOrders();
-    List<TabOrder> findTabOrdersByTableAndDate(Integer tableNumber, LocalDate date);
-    List<TabOrder> findTabOrdersByStaff(Long frontStaffId);
-    TabOrder assignOrderToStaff(Long orderId, Long frontStaffId);
-
-    List<Order> findOpenOrders();
-    List<Order> findClosedOrders();
-
-    // General methods for all order types
-    Order cancelOrder(Long orderId);
-}
Index: c/main/java/finki/db/tasty_tabs/service/PaymentService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/PaymentService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,14 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.Payment;
-import finki.db.tasty_tabs.web.dto.CreatePaymentDto;
-
-import java.util.List;
-
-public interface PaymentService {
-    Payment createPayment(CreatePaymentDto dto);
-    Payment findPaymentById(Long id);
-    Payment findPaymentByOrderId(Long orderId);
-    List<Payment> findAllPayments();
-    Payment updatePayment(Long id, CreatePaymentDto dto);
-}
Index: c/main/java/finki/db/tasty_tabs/service/ProductService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/ProductService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.Product;
-import finki.db.tasty_tabs.web.dto.CreateProductDto;
-
-import java.util.List;
-
-public interface ProductService {
-    Product findById(Long id);
-    List<Product> getAllProducts();
-    Product updateProduct(Long id, CreateProductDto dto);
-    void deleteProduct(Long id);
-    List<Product> getProductsByName(String name);
-    Product createProduct(CreateProductDto dto);
-}
Index: c/main/java/finki/db/tasty_tabs/service/ReservationService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/ReservationService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,22 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.Reservation;
-import finki.db.tasty_tabs.entity.ReservationManagedFrontStaff;
-import finki.db.tasty_tabs.web.dto.CreateReservationDto;
-import finki.db.tasty_tabs.web.dto.ReservationDto;
-
-import java.time.LocalDate;
-import java.util.List;
-
-public interface ReservationService {
-    List<Reservation> getAllReservations();
-    Reservation getReservationById(Long id);
-    Reservation createReservation(CreateReservationDto dto,String userEmail);
-    Reservation updateReservation(Long id, CreateReservationDto dto,String userEmail);
-    void deleteReservation(Long id);
-    List<Reservation> getAllReservationsByUser(String userEmail);
-    ReservationManagedFrontStaff acceptReservation(Long reservationId, String frontStaffEmail, Integer tableNumber);
-
-    List<Reservation> getAllReservationsForToday();
-    List<Reservation> getAllReservationsForDate(LocalDate date);
-}
Index: c/main/java/finki/db/tasty_tabs/service/RestaurantTableService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/RestaurantTableService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,16 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.RestaurantTable;
-
-import java.util.List;
-import java.util.Optional;
-
-public interface RestaurantTableService {
-
-    RestaurantTable findById(Integer id);
-    List<RestaurantTable> getAll();
-    RestaurantTable updateTable(Integer id,RestaurantTable restaurantTable);
-    void deleteTable(Integer id);
-    List<RestaurantTable> getAllBySeatCapacity(Integer seatCapacity);
-    RestaurantTable createTable(RestaurantTable restaurantTable);
-}
Index: c/main/java/finki/db/tasty_tabs/service/ShiftService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/ShiftService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package finki.db.tasty_tabs.service;
-
-import finki.db.tasty_tabs.entity.Shift;
-import finki.db.tasty_tabs.web.dto.CreateShiftDto;
-import org.springframework.security.core.userdetails.UserDetails;
-
-import java.util.List;
-
-public interface ShiftService {
-    List<Shift> getAllShifts();
-    Shift getShiftById(Long id);
-    Shift createShift(CreateShiftDto dto, String username);
-    Shift updateShift(Long id, CreateShiftDto dto, String username);
-    void deleteShift(Long id, String username);
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/AssignmentServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/AssignmentServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,130 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.Assignment;
-import finki.db.tasty_tabs.entity.Employee;
-import finki.db.tasty_tabs.entity.Manager;
-import finki.db.tasty_tabs.entity.Shift;
-import finki.db.tasty_tabs.entity.exceptions.AssignmentNotFoundException;
-import finki.db.tasty_tabs.entity.exceptions.EmployeeNotFoundException;
-import finki.db.tasty_tabs.entity.exceptions.ShiftNotFoundException;
-import finki.db.tasty_tabs.repository.AssignmentRepository;
-import finki.db.tasty_tabs.repository.EmployeeRepository;
-import finki.db.tasty_tabs.repository.ManagerRepository;
-import finki.db.tasty_tabs.repository.ShiftRepository;
-import finki.db.tasty_tabs.service.AssignmentService;
-import finki.db.tasty_tabs.web.dto.CreateAssignmentDto;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.stereotype.Service;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Service
-public class AssignmentServiceImpl implements AssignmentService {
-
-    private final AssignmentRepository assignmentRepository;
-    private final ManagerRepository managerRepository;
-    private final EmployeeRepository employeeRepository;
-    private final ShiftRepository shiftRepository;
-
-    public AssignmentServiceImpl(AssignmentRepository assignmentRepository, ManagerRepository managerRepository, EmployeeRepository employeeRepository, ShiftRepository shiftRepository) {
-        this.assignmentRepository = assignmentRepository;
-        this.managerRepository = managerRepository;
-        this.employeeRepository = employeeRepository;
-        this.shiftRepository = shiftRepository;
-    }
-
-    private Manager getManagerByEmail(String email) {
-        return managerRepository.findByEmail(email)
-                .orElseThrow(() -> new AccessDeniedException("Only managers can assign assignments."));
-    }
-
-    @Override
-    public List<Assignment> getAllAssignments() {
-        return assignmentRepository.findAll();
-    }
-
-    @Override
-    public Assignment getAssignmentById(Long id) {
-        return assignmentRepository.findById(id)
-                .orElseThrow(() -> new AssignmentNotFoundException(id));
-    }
-
-    @Override
-    public Assignment createAssignment(CreateAssignmentDto dto, String managerEmail) {
-        Manager manager = getManagerByEmail(managerEmail);
-        Employee employee = employeeRepository.findById(dto.employeeId())
-                .orElseThrow(() -> new EmployeeNotFoundException(dto.employeeId()));
-        Shift shift = shiftRepository.findById(dto.shiftId())
-                .orElseThrow(() -> new ShiftNotFoundException(dto.shiftId()));
-
-        Assignment assignment = new Assignment(
-                dto.clockInTime(),
-                dto.clockOutTime(),
-                manager,
-                employee,
-                shift
-        );
-
-        return assignmentRepository.save(assignment);
-    }
-
-    @Override
-    public Assignment updateAssignment(Long id, CreateAssignmentDto dto, String managerEmail) {
-        Manager manager = getManagerByEmail(managerEmail);
-        Assignment assignment = getAssignmentById(id);
-
-        Employee employee = employeeRepository.findById(dto.employeeId())
-                .orElseThrow(() -> new EmployeeNotFoundException(dto.employeeId()));
-        Shift shift = shiftRepository.findById(dto.shiftId())
-                .orElseThrow(() -> new ShiftNotFoundException(dto.shiftId()));
-
-        assignment.setClockInTime(dto.clockInTime());
-        assignment.setClockOutTime(dto.clockOutTime());
-        assignment.setManager(manager);
-        assignment.setEmployee(employee);
-        assignment.setShift(shift);
-
-        return assignmentRepository.save(assignment);
-    }
-
-    @Override
-    public void deleteAssignment(Long id, String managerEmail) {
-        getManagerByEmail(managerEmail);
-        if (!assignmentRepository.existsById(id)) {
-            throw new AssignmentNotFoundException(id);
-        }
-        assignmentRepository.deleteById(id);
-    }
-    @Override
-    public Assignment clockInShift(Long assignmentId, String employeeEmail, LocalDateTime clockInTime) {
-        Assignment assignment = assignmentRepository.findById(assignmentId)
-                .orElseThrow(() -> new AssignmentNotFoundException( assignmentId));
-
-        // Check if the logged-in employee is assigned to this assignment
-        if (!assignment.getEmployee().getEmail().equals(employeeEmail)) {
-            throw new AccessDeniedException("You can only clock in your own shift.");
-        }
-
-        assignment.setClockInTime(clockInTime);
-        return assignmentRepository.save(assignment);
-    }
-
-    @Override
-    public Assignment clockOutShift(Long assignmentId, String employeeEmail, LocalDateTime clockOutTime) {
-        Assignment assignment = assignmentRepository.findById(assignmentId)
-                .orElseThrow(() -> new AssignmentNotFoundException(assignmentId));
-
-        if (!assignment.getEmployee().getEmail().equals(employeeEmail)) {
-            throw new AccessDeniedException("You can only clock out your own shift.");
-        }
-
-        if (assignment.getClockInTime() == null) {
-            throw new IllegalStateException("Cannot clock out without clocking in first.");
-        }
-
-        assignment.setClockOutTime(clockOutTime);
-        return assignmentRepository.save(assignment);
-    }
-
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/AuthServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/AuthServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,66 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.User;
-import finki.db.tasty_tabs.repository.UserRepository;
-import finki.db.tasty_tabs.service.AuthService;
-import finki.db.tasty_tabs.utils.JwtProvider;
-import finki.db.tasty_tabs.web.dto.AuthDto;
-import finki.db.tasty_tabs.web.dto.RegisterRequest;
-import finki.db.tasty_tabs.web.dto.UserDto;
-import jakarta.transaction.Transactional;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
-
-import java.util.HashSet;
-
-@Service
-public class AuthServiceImpl implements AuthService {
-    private final UserRepository userRepository;
-    private final JwtProvider jwtProvider;
-    private final AuthenticationManager authenticationManager;
-    private final PasswordEncoder passwordEncoder;
-
-    public AuthServiceImpl(UserRepository userRepository, JwtProvider jwtProvider, AuthenticationManager authenticationManager, PasswordEncoder passwordEncoder) {
-        this.userRepository = userRepository;
-        this.jwtProvider = jwtProvider;
-        this.authenticationManager = authenticationManager;
-        this.passwordEncoder = passwordEncoder;
-    }
-
-    @Override
-    public AuthDto authenticate(String email, String password) {
-        Authentication authentication = authenticationManager.authenticate(
-                new UsernamePasswordAuthenticationToken(email, password)
-        );
-
-        User user = userRepository.findByEmail(email)
-                .orElseThrow(() -> new RuntimeException("User not found"));
-
-        String token = jwtProvider.generateToken(user.getEmail());
-
-        return new AuthDto(
-                token,
-                UserDto.from(user)
-        );
-    }
-
-
-    @Override
-    @Transactional
-    public AuthDto register(RegisterRequest request) {
-        throw new RuntimeException("Not implemented");
-    }
-
-    @Override
-    public UserDto getAuthenticatedUser() {
-        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-
-        return UserDto.from(userRepository.findByEmail(authentication.getName())
-                .orElseThrow(() -> new RuntimeException("User not found")));
-    }
-
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/CategoryServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/CategoryServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,58 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.Category;
-import finki.db.tasty_tabs.entity.exceptions.CategoryNotFoundException;
-import finki.db.tasty_tabs.repository.CategoryRepository;
-import finki.db.tasty_tabs.service.CategoryService;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-@Service
-public class CategoryServiceImpl implements CategoryService {
-
-    private final CategoryRepository categoryRepository;
-
-    public CategoryServiceImpl(CategoryRepository categoryRepository) {
-        this.categoryRepository = categoryRepository;
-    }
-
-    @Override
-    public Category findById(Long id) {
-        return categoryRepository.findById(id).orElseThrow(CategoryNotFoundException::new);
-    }
-
-    @Override
-    public List<Category> getAllCategories() {
-        return categoryRepository.findAll();
-    }
-
-    @Override
-    public Category updateCategory(Long id, Category category) {
-        return categoryRepository.findById(id).map(existingCategory -> {
-            if (category.getName() != null) {
-                existingCategory.setName(category.getName());
-            }
-            if (category.getIsAvailable() != null) {
-                existingCategory.setIsAvailable(category.getIsAvailable());
-            }
-            return categoryRepository.save(existingCategory);
-        }).orElseThrow(CategoryNotFoundException::new);
-    }
-
-    @Override
-    public void deleteCategory(Long id) {
-        categoryRepository.deleteById(id);
-    }
-
-    @Override
-    public Category getCategoryByName(String name) {
-        return categoryRepository.findByName(name).orElseThrow(CategoryNotFoundException::new);
-    }
-
-    @Override
-    public Category createCategory(Category category) {
-        return categoryRepository.save(category);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/EmployeeServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/EmployeeServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,82 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.*;
-import finki.db.tasty_tabs.repository.*;
-import finki.db.tasty_tabs.service.EmployeeService;
-import finki.db.tasty_tabs.web.dto.CreateEmployeeRequest;
-import jakarta.persistence.EntityNotFoundException;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import static finki.db.tasty_tabs.entity.EmployeeType.*;
-
-@Service
-@Transactional
-class EmployeeServiceImpl implements EmployeeService { // New Service Implementation
-
-    private final UserRepository userRepository;
-    private final ManagerRepository managerRepository;
-    private final FrontStaffRepository frontStaffRepository;
-    private final BackStaffRepository backStaffRepository;
-    private final StaffRoleRepository staffRoleRepository;
-    private final PasswordEncoder passwordEncoder;
-
-    public EmployeeServiceImpl(UserRepository userRepository, ManagerRepository managerRepository, FrontStaffRepository frontStaffRepository, BackStaffRepository backStaffRepository, StaffRoleRepository staffRoleRepository, PasswordEncoder passwordEncoder) {
-        this.userRepository = userRepository;
-        this.managerRepository = managerRepository;
-        this.frontStaffRepository = frontStaffRepository;
-        this.backStaffRepository = backStaffRepository;
-        this.staffRoleRepository = staffRoleRepository;
-        this.passwordEncoder = passwordEncoder;
-    }
-
-    @Override
-    public Employee createEmployee(CreateEmployeeRequest request) {
-        // In a real app, you'd check if email is unique and hash the password
-        if (userRepository.existsByEmail(request.email())) {
-             throw new IllegalArgumentException("Employee with email " + request.email() + " already exists.");
-        }
-
-        Employee employee;
-
-        switch (request.employeeType()) {
-            case MANAGER:
-                Manager manager = new Manager();
-                setCommonEmployeeFields(manager, request);
-                employee = managerRepository.save(manager);
-                break;
-            case FRONT_STAFF:
-                FrontStaff frontStaff = new FrontStaff();
-                setCommonEmployeeFields(frontStaff, request);
-                StaffRole frontStaffRole = staffRoleRepository.findById(request.staffRoleId())
-                        .orElseThrow(() -> new EntityNotFoundException("StaffRole not found with id: " + request.staffRoleId()));
-                frontStaff.setStaffRole(frontStaffRole);
-                frontStaff.setTipPercent(request.tipPercent());
-                employee = frontStaffRepository.save(frontStaff);
-                break;
-            case BACK_STAFF:
-                BackStaff backStaff = new BackStaff();
-                setCommonEmployeeFields(backStaff, request);
-                StaffRole backStaffRole = staffRoleRepository.findById(request.staffRoleId())
-                        .orElseThrow(() -> new EntityNotFoundException("StaffRole not found with id: " + request.staffRoleId()));
-                backStaff.setStaffRole(backStaffRole);
-                employee = backStaffRepository.save(backStaff);
-                break;
-            default:
-                throw new IllegalArgumentException("Invalid employee type: " + request.email());
-        }
-
-        return employee;
-    }
-
-    private void setCommonEmployeeFields(Employee employee, CreateEmployeeRequest request) {
-        employee.setEmail(request.email());
-        employee.setPassword(passwordEncoder.encode(request.password()));
-        employee.setStreet(request.street());
-        employee.setCity(request.city());
-        employee.setPhoneNumber(request.phoneNumber());
-        employee.setNetSalary(request.netSalary());
-        employee.setGrossSalary(request.grossSalary());
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/OrderServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/OrderServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,302 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.*;
-import finki.db.tasty_tabs.entity.exceptions.*;
-import finki.db.tasty_tabs.repository.*;
-import finki.db.tasty_tabs.service.OrderService;
-import finki.db.tasty_tabs.web.dto.CreateOrderDto;
-import finki.db.tasty_tabs.web.dto.CreateOrderItemDto;
-import jakarta.transaction.Transactional;
-import lombok.RequiredArgsConstructor;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.stereotype.Service;
-
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@Service
-@RequiredArgsConstructor
-public class OrderServiceImpl implements OrderService {
-
-    private final OrderRepository orderRepository;
-    private final OrderItemRepository orderItemRepository;
-    private final ProductRepository productRepository;
-    private final RestaurantTableRepository tableRepository;
-    private final UserRepository userRepository;
-    private final TabOrderRepository tabOrderRepository;
-    private final OnlineOrderRepository onlineOrderRepository;
-    private final FrontStaffRepository frontStaffRepository;
-    private final CustomerRepository customerRepository;
-
-    @Override
-    public List<Order> findAll() {
-        return orderRepository.findAll();
-    }
-
-    @Override
-    public Order findById(Long id) {
-        return orderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException(id));
-    }
-
-    @Override
-    public Order updateOrder(Long id, CreateOrderDto dto) {
-        Order existingOrder = findById(id);
-
-        existingOrder.setStatus(dto.status());
-
-        existingOrder.getOrderItems().clear();
-        List<OrderItem> newOrderItems = dto.orderItems().stream().map(itemDto -> {
-            OrderItem item = new OrderItem();
-            item.setOrder(existingOrder);
-            item.setQuantity(itemDto.quantity());
-            item.setPrice(itemDto.price());
-            item.setIsProcessed(itemDto.isProcessed());
-            item.setTimestamp(LocalDateTime.now());
-            Product product = productRepository.findById(itemDto.productId())
-                    .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
-            item.setProduct(product);
-            return item;
-        }).collect(Collectors.toList());
-
-        existingOrder.setOrderItems(newOrderItems);
-
-        return orderRepository.save(existingOrder);
-    }
-
-    @Override
-    public void deleteOrder(Long id) {
-        orderRepository.deleteById(id);
-    }
-
-    @Override
-    public double calculateTotalPrice(Long orderId) {
-        Order order = findById(orderId);
-        return order.getOrderItems().stream()
-                .mapToDouble(item -> item.getQuantity() * item.getPrice())
-                .sum();
-    }
-
-    @Override
-    public void updateOrderStatus(Long orderId, String newStatus) {
-        Order order = findById(orderId);
-        order.setStatus(newStatus);
-        orderRepository.save(order);
-    }
-
-    // Methods for Order Items
-    @Override
-    @Transactional
-    public OrderItem addItemToOrder(Long orderId, CreateOrderItemDto itemDto) {
-        Order order = findById(orderId);
-        OrderItem orderItem = new OrderItem();
-        orderItem.setOrder(order);
-        orderItem.setQuantity(itemDto.quantity());
-        orderItem.setPrice(itemDto.price());
-        orderItem.setIsProcessed(itemDto.isProcessed());
-        orderItem.setTimestamp(LocalDateTime.now());
-        Product product = productRepository.findById(itemDto.productId())
-                .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
-        orderItem.setProduct(product);
-        return orderItemRepository.save(orderItem);
-    }
-
-    @Override
-    @Transactional
-    public void decreaseOrderItemQuantity(Long orderItemId) {
-        OrderItem orderItem = orderItemRepository.findById(orderItemId)
-                .orElseThrow(OrderItemNotFoundException::new);
-        if (orderItem.getQuantity() > 1) {
-            orderItem.setQuantity(orderItem.getQuantity() - 1);
-            orderItemRepository.save(orderItem);
-        } else {
-            orderItemRepository.delete(orderItem);
-        }
-    }
-
-    @Override
-    @Transactional
-    public OrderItem updateOrderItem(Long orderItemId, CreateOrderItemDto itemDto) {
-        OrderItem orderItem = orderItemRepository.findById(orderItemId)
-                .orElseThrow(OrderItemNotFoundException::new);
-        orderItem.setQuantity(itemDto.quantity());
-        orderItem.setPrice(itemDto.price());
-        orderItem.setIsProcessed(itemDto.isProcessed());
-        Product product = productRepository.findById(itemDto.productId())
-                .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
-        orderItem.setProduct(product);
-        return orderItemRepository.save(orderItem);
-    }
-
-    @Override
-    @Transactional
-    public void deleteOrderItem(Long orderItemId) {
-        orderItemRepository.deleteById(orderItemId);
-    }
-
-    @Override
-    @Transactional
-    public OrderItem processOrderItem(Long orderItemId) {
-        OrderItem orderItem = orderItemRepository.findById(orderItemId)
-                .orElseThrow(OrderItemNotFoundException::new);
-        orderItem.setIsProcessed(true);
-        return orderItemRepository.save(orderItem);
-    }
-
-    // Specific OnlineOrder methods
-    @Override
-    @Transactional
-    public OnlineOrder createOnlineOrder(CreateOrderDto dto, String userEmail) {
-        User user = userRepository.findByEmail(userEmail)
-                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
-        if (!(user instanceof Customer)) {
-            throw new SecurityException("User is not authorized to create online orders.");
-        }
-        OnlineOrder onlineOrder = new OnlineOrder();
-        onlineOrder.setCustomer((Customer) user);
-        onlineOrder.setDeliveryAddress(dto.deliveryAddress());
-        onlineOrder.setTimestamp(LocalDateTime.now());
-        onlineOrder.setStatus(dto.status());
-        if (dto.orderItems() != null && !dto.orderItems().isEmpty()) {
-            List<OrderItem> orderItems = dto.orderItems().stream().map(itemDto -> {
-                OrderItem item = new OrderItem();
-                item.setOrder(onlineOrder);
-                item.setQuantity(itemDto.quantity());
-                item.setPrice(itemDto.price());
-                item.setIsProcessed(itemDto.isProcessed());
-                item.setTimestamp(LocalDateTime.now());
-                Product product = productRepository.findById(itemDto.productId())
-                        .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
-                item.setProduct(product);
-                return item;
-            }).collect(Collectors.toList());
-            onlineOrder.setOrderItems(orderItems);
-        }
-        return onlineOrderRepository.save(onlineOrder);
-    }
-
-    @Override
-    public OnlineOrder findOnlineOrderById(Long id) {
-        return onlineOrderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException(id));
-    }
-
-    @Override
-    public List<OnlineOrder> findAllOnlineOrders() {
-        return onlineOrderRepository.findAll();
-    }
-
-    @Override
-    public List<OnlineOrder> findOnlineOrdersByCustomer(Long customerId) {
-        return onlineOrderRepository.findAllByCustomer_Id(customerId);
-    }
-
-    // Specific TabOrder methods
-    @Override
-    @Transactional
-    public TabOrder createTabOrder(CreateOrderDto dto, String userEmail) {
-        User user = userRepository.findByEmail(userEmail)
-                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
-        if (!(user instanceof FrontStaff)) {
-            throw new SecurityException("User is not authorized to create tab orders.");
-        }
-        TabOrder tabOrder = new TabOrder();
-        RestaurantTable table = tableRepository.findById(dto.tableNumber())
-                .orElseThrow(() -> new TableNotFoundException(dto.tableNumber()));
-        tabOrder.setRestaurantTable(table);
-        tabOrder.setFrontStaff((FrontStaff) user);
-        tabOrder.setTimestamp(LocalDateTime.now());
-        tabOrder.setStatus(dto.status());
-        if (dto.orderItems() != null && !dto.orderItems().isEmpty()) {
-            List<OrderItem> orderItems = dto.orderItems().stream().map(itemDto -> {
-                OrderItem item = new OrderItem();
-                item.setOrder(tabOrder);
-                item.setQuantity(itemDto.quantity());
-                item.setPrice(itemDto.price());
-                item.setIsProcessed(itemDto.isProcessed());
-                item.setTimestamp(LocalDateTime.now());
-                Product product = productRepository.findById(itemDto.productId())
-                        .orElseThrow(() -> new ProductNotFoundException(itemDto.productId()));
-                item.setProduct(product);
-                return item;
-            }).collect(Collectors.toList());
-            tabOrder.setOrderItems(orderItems);
-        }
-        return tabOrderRepository.save(tabOrder);
-    }
-
-    @Override
-    public TabOrder findTabOrderById(Long id) {
-        return tabOrderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException(id));
-    }
-
-    @Override
-    public List<TabOrder> findAllTabOrders() {
-        return tabOrderRepository.findAll();
-    }
-
-    @Override
-    public List<TabOrder> findTabOrdersByTableAndDate(Integer tableNumber, LocalDate date) {
-        LocalDateTime startOfDay = date.atStartOfDay();
-        LocalDateTime endOfDay = date.atTime(23, 59, 59);
-        return tabOrderRepository.findByRestaurantTable_TableNumberAndTimestampBetween(tableNumber, startOfDay, endOfDay);
-    }
-
-    @Override
-    public List<TabOrder> findTabOrdersByStaff(Long frontStaffId) {
-        return tabOrderRepository.findAllByFrontStaffId(frontStaffId);
-    }
-
-    @Override
-    @Transactional
-    public TabOrder assignOrderToStaff(Long orderId, Long frontStaffId) {
-        TabOrder tabOrder = tabOrderRepository.findById(orderId)
-                .orElseThrow(() -> new OrderNotFoundException(orderId));
-        FrontStaff frontStaff = frontStaffRepository.findById(frontStaffId)
-                .orElseThrow(() -> new FrontStaffNotFoundException(frontStaffId));
-        tabOrder.setFrontStaff(frontStaff);
-        return tabOrderRepository.save(tabOrder);
-    }
-
-    // General methods for all order types
-    @Override
-    @Transactional
-    public Order cancelOrder(Long orderId) {
-        Order order = findById(orderId);
-        order.setStatus("CANCELED");
-        return orderRepository.save(order);
-    }
-
-    @Override
-    public List<Order> findOpenOrders() {
-
-        // Query the OnlineOrderRepository for open orders
-        List<OnlineOrder> onlineOrders = onlineOrderRepository.findAllByStatus("OPEN");
-
-        // Query the TabOrderRepository for open orders
-        List<TabOrder> tabOrders = tabOrderRepository.findAllByStatus("OPEN");
-
-        // Combine the lists into a single List<Order>
-        List<Order> combinedOrders = new java.util.ArrayList<>();
-        combinedOrders.addAll(onlineOrders);
-        combinedOrders.addAll(tabOrders);
-
-        return combinedOrders;
-    }
-
-    @Override
-    public List<Order> findClosedOrders() {
-
-        // Query the OnlineOrderRepository for open orders
-        List<OnlineOrder> onlineOrders = onlineOrderRepository.findAllByStatus("CLOSED");
-
-        // Query the TabOrderRepository for open orders
-        List<TabOrder> tabOrders = tabOrderRepository.findAllByStatus("CLOSED");
-
-        // Combine the lists into a single List<Order>
-        List<Order> combinedOrders = new java.util.ArrayList<>();
-        combinedOrders.addAll(onlineOrders);
-        combinedOrders.addAll(tabOrders);
-
-        return combinedOrders;    }
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/PaymentServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/PaymentServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,71 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-
-import finki.db.tasty_tabs.entity.Order;
-import finki.db.tasty_tabs.entity.Payment;
-import finki.db.tasty_tabs.entity.exceptions.OrderNotFoundException;
-import finki.db.tasty_tabs.entity.exceptions.PaymentNotFoundException;
-import finki.db.tasty_tabs.repository.OrderRepository;
-import finki.db.tasty_tabs.repository.PaymentRepository;
-import finki.db.tasty_tabs.service.PaymentService;
-import finki.db.tasty_tabs.web.dto.CreatePaymentDto;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import jakarta.transaction.Transactional;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Service
-@RequiredArgsConstructor
-public class PaymentServiceImpl implements PaymentService {
-
-    private final PaymentRepository paymentRepository;
-    private final OrderRepository orderRepository;
-
-    @Override
-    @Transactional
-    public Payment createPayment(CreatePaymentDto dto) {
-        Order order = orderRepository.findById(dto.orderId())
-                .orElseThrow(() -> new OrderNotFoundException(dto.orderId()));
-
-        Payment payment = new Payment();
-        payment.setAmount(dto.amount());
-        payment.setTipAmount(dto.tipAmount());
-        payment.setPaymentType(dto.paymentType());
-        payment.setTimestamp(LocalDateTime.now());
-        payment.setOrder(order);
-
-        return paymentRepository.save(payment);
-    }
-
-    @Override
-    public Payment findPaymentById(Long id) {
-        return paymentRepository.findById(id)
-                .orElseThrow(() -> new PaymentNotFoundException(id));
-    }
-
-    @Override
-    public Payment findPaymentByOrderId(Long orderId) {
-        return paymentRepository.findByOrderId(orderId)
-                .orElseThrow(() -> new PaymentNotFoundException(orderId));
-    }
-
-    @Override
-    public List<Payment> findAllPayments() {
-        return paymentRepository.findAll();
-    }
-
-    @Override
-    @Transactional
-    public Payment updatePayment(Long id, CreatePaymentDto dto) {
-        Payment existingPayment = findPaymentById(id);
-
-        existingPayment.setAmount(dto.amount());
-        existingPayment.setTipAmount(dto.tipAmount());
-        existingPayment.setPaymentType(dto.paymentType());
-
-        return paymentRepository.save(existingPayment);
-    }
-
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/ProductServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/ProductServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,131 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-
-import finki.db.tasty_tabs.entity.Inventory;
-import finki.db.tasty_tabs.entity.Product;
-import finki.db.tasty_tabs.entity.exceptions.ProductNotFoundException;
-import finki.db.tasty_tabs.repository.InventoryRepository;
-import finki.db.tasty_tabs.repository.ProductRepository;
-import finki.db.tasty_tabs.service.CategoryService;
-import finki.db.tasty_tabs.service.ProductService;
-import finki.db.tasty_tabs.web.dto.CreateProductDto;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-@Service
-public class ProductServiceImpl implements ProductService {
-
-    private final ProductRepository productRepository;
-    private final CategoryService categoryService;
-    private final InventoryRepository inventoryRepository;
-
-
-    public ProductServiceImpl(ProductRepository productRepository, CategoryService categoryService,InventoryRepository inventoryRepository) {
-        this.productRepository = productRepository;
-        this.categoryService = categoryService;
-        this.inventoryRepository=inventoryRepository;
-    }
-
-    @Override
-    public Product findById(Long id) {
-        return productRepository.findById(id)
-                .orElseThrow(() -> new ProductNotFoundException(id));
-    }
-
-    @Override
-    public List<Product> getAllProducts() {
-        return productRepository.findAll();
-    }
-
-    @Override
-    public Product updateProduct(Long id, CreateProductDto dto) {
-        Product existingProduct = productRepository.findById(id)
-                .orElseThrow(() -> new ProductNotFoundException(id));
-
-        // Update product fields
-        if (dto.name() != null) {
-            existingProduct.setName(dto.name());
-        }
-        if (dto.price() != null) {
-            existingProduct.setPrice(dto.price());
-        }
-        if (dto.taxClass() != null) {
-            existingProduct.setTaxClass(dto.taxClass());
-        }
-        if (dto.categoryId() != null) {
-            existingProduct.setCategory(categoryService.findById(dto.categoryId()));
-        }
-        if (dto.description() != null) {
-            existingProduct.setDescription(dto.description());
-        }
-
-        // Manage inventory
-        if (Boolean.TRUE.equals(dto.manageInventory())) {
-            // ако производот претходно не менаџирал inventory -> креирај нов
-            if (Boolean.FALSE.equals(existingProduct.getManageInventory())) {
-                Inventory inventory = new Inventory(existingProduct, dto.quantity(), dto.restockLevel());
-                inventoryRepository.save(inventory);
-            } else {
-                // ако веќе постои -> update
-                Inventory inventory = inventoryRepository.findById(id)
-                        .orElseThrow(() -> new RuntimeException("Inventory not found for product " + id));
-                if (dto.quantity() != null) {
-                    inventory.setQuantity(dto.quantity());
-                }
-                if (dto.restockLevel() != null) {
-                    inventory.setRestockLevel(dto.restockLevel());
-                }
-                inventoryRepository.save(inventory);
-            }
-        } else if (Boolean.FALSE.equals(dto.manageInventory())) {
-            // ако од TRUE се префрла на FALSE -> бриши го inventory-то
-            inventoryRepository.findById(id).ifPresent(inventoryRepository::delete);
-        }
-
-        // на крај секогаш го сетирај manageInventory флагот
-        if (dto.manageInventory() != null) {
-            existingProduct.setManageInventory(dto.manageInventory());
-        }
-
-        return productRepository.save(existingProduct);
-    }
-
-    @Override
-    public void deleteProduct(Long id) {
-        productRepository.deleteById(id);
-    }
-
-    @Override
-    public List<Product> getProductsByName(String name) {
-
-        return productRepository.findAllByName(name);
-    }
-
-    @Override
-    public Product createProduct(CreateProductDto dto) {
-        Product productTmp=new Product();
-        if (dto.name() != null) {
-            productTmp.setName(dto.name());
-        }
-        if (dto.price() != null) {
-            productTmp.setPrice(dto.price());
-        }
-        if(dto.taxClass()!=null){
-            productTmp.setTaxClass(dto.taxClass());
-        }
-        productTmp.setCategory(categoryService.findById(dto.categoryId()));
-        productTmp.setDescription(dto.description());
-
-        if(dto.manageInventory()!=null){
-            productTmp.setManageInventory(dto.manageInventory());
-        }
-        Product product=productRepository.save(productTmp);
-        if(product.getManageInventory()==Boolean.TRUE){
-            Inventory inventory = new Inventory(product, dto.quantity(), dto.restockLevel());
-            inventoryRepository.save(inventory);
-        }
-        return product;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/ReservationServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/ReservationServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,133 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.*;
-import finki.db.tasty_tabs.entity.exceptions.ReservationNotFoundException;
-import finki.db.tasty_tabs.entity.exceptions.TableNotFoundException;
-import finki.db.tasty_tabs.repository.*;
-import finki.db.tasty_tabs.service.ReservationService;
-import finki.db.tasty_tabs.web.dto.CreateReservationDto;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.stereotype.Service;
-
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Service
-public class ReservationServiceImpl implements ReservationService {
-
-    private final ReservationRepository reservationRepository;
-    private final UserRepository userRepository;
-    private final FrontStaffRepository frontStaffRepository;
-    private final RestaurantTableRepository restaurantTableRepository;
-    private final ReservationManagedFrontStaffRepository reservationManagedFrontStaffRepository;
-
-    public ReservationServiceImpl(ReservationRepository reservationRepository, UserRepository userRepository, FrontStaffRepository frontStaffRepository, RestaurantTableRepository restaurantTableRepository, ReservationManagedFrontStaffRepository reservationManagedFrontStaffRepository) {
-        this.reservationRepository = reservationRepository;
-        this.userRepository = userRepository;
-        this.frontStaffRepository = frontStaffRepository;
-        this.restaurantTableRepository = restaurantTableRepository;
-        this.reservationManagedFrontStaffRepository = reservationManagedFrontStaffRepository;
-    }
-
-    @Override
-    public List<Reservation> getAllReservations() {
-        return reservationRepository.findAll();
-    }
-
-    @Override
-    public Reservation getReservationById(Long id) {
-        return reservationRepository.findById(id)
-                .orElseThrow(() -> new ReservationNotFoundException(id));
-    }
-
-    @Override
-    public Reservation createReservation(CreateReservationDto dto, String userEmail) {
-        User user = userRepository.findByEmail(userEmail)
-                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
-
-        Reservation reservation = new Reservation();
-        reservation.setStayLength(dto.stayLength());
-        reservation.setDatetime(dto.datetime());
-        reservation.setNumberOfPeople(dto.numberOfPeople());
-        reservation.setUser(user);
-        reservation.setCreationTimestamp(LocalDateTime.now());
-
-        return reservationRepository.save(reservation);
-    }
-
-    @Override
-    public Reservation updateReservation(Long id, CreateReservationDto dto, String userEmail) {
-        Reservation existing = getReservationById(id);
-
-        User user = userRepository.findByEmail(userEmail)
-                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
-
-        // Optionally, add a check if the logged-in user is allowed to update this reservation
-        if (!existing.getUser().getId().equals(user.getId())) {
-            throw new SecurityException("You are not authorized to update this reservation.");
-        }
-
-        existing.setStayLength(dto.stayLength());
-        existing.setDatetime(dto.datetime());
-        existing.setNumberOfPeople(dto.numberOfPeople());
-        existing.setUser(user);
-
-        return reservationRepository.save(existing);
-    }
-
-    @Override
-    public void deleteReservation(Long id) {
-        reservationRepository.deleteById(id);
-    }
-
-    @Override
-    public List<Reservation> getAllReservationsByUser(String userEmail) {
-        User user = userRepository.findByEmail(userEmail)
-                .orElseThrow(() -> new UsernameNotFoundException("User with email " + userEmail + " not found."));
-        return reservationRepository.findAllByUser(user);
-    }
-
-    @Override
-    public ReservationManagedFrontStaff acceptReservation(Long reservationId, String frontStaffEmail, Integer tableNumber) {
-        User user = userRepository.findByEmail(frontStaffEmail)
-                .orElseThrow(() -> new UsernameNotFoundException("User with email " + frontStaffEmail + " not found."));
-
-        if (!(user instanceof FrontStaff)) {
-            throw new SecurityException("User is not authorized to accept reservations as they are not a FrontStaff member.");
-        }
-        FrontStaff frontStaff = (FrontStaff) user;
-        // 2. Fetch all other required entities
-        Reservation reservation = reservationRepository.findById(reservationId)
-                .orElseThrow(() -> new ReservationNotFoundException(reservationId));
-
-        RestaurantTable table = restaurantTableRepository.findById(tableNumber)
-                .orElseThrow(() -> new TableNotFoundException(tableNumber));
-
-        // 3. Create the new ReservationManagedFrontStaff entity
-        ReservationManagedFrontStaff managedReservation = new ReservationManagedFrontStaff();
-        managedReservation.setReservation(reservation);
-        managedReservation.setFrontStaff(frontStaff);
-        managedReservation.setRestaurantTable(table);
-
-        // 4. Save the new entity to the database
-        return reservationManagedFrontStaffRepository.save(managedReservation);
-    }
-    @Override
-    public List<Reservation> getAllReservationsForToday() {
-        LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
-        LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59);
-
-        return reservationRepository.findAllByDatetimeBetween(startOfDay, endOfDay);
-    }
-
-    @Override
-    public List<Reservation> getAllReservationsForDate(LocalDate date) {
-        LocalDateTime startOfDay = date.atStartOfDay();
-        LocalDateTime endOfDay = date.atTime(23, 59, 59);
-
-        return reservationRepository.findAllByDatetimeBetween(startOfDay, endOfDay);
-    }
-
-}
-
Index: c/main/java/finki/db/tasty_tabs/service/impl/RestaurantTableServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/RestaurantTableServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,66 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.RestaurantTable;
-import finki.db.tasty_tabs.entity.exceptions.TableNotFoundException;
-import finki.db.tasty_tabs.entity.exceptions.TableNumberAlreadyExistsException;
-import finki.db.tasty_tabs.repository.RestaurantTableRepository;
-import finki.db.tasty_tabs.service.RestaurantTableService;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-@Service
-public class RestaurantTableServiceImpl implements RestaurantTableService {
-
-    private final RestaurantTableRepository tableRepository;
-
-    public RestaurantTableServiceImpl(RestaurantTableRepository tableRepository) {
-        this.tableRepository = tableRepository;
-    }
-
-    @Override
-    public RestaurantTable findById(Integer id) {
-        return tableRepository.findById(id).orElseThrow(()->new TableNotFoundException(id));
-    }
-
-    @Override
-    public List<RestaurantTable> getAll() {
-        return tableRepository.findAll();
-    }
-
-    @Override
-    public RestaurantTable updateTable(Integer id, RestaurantTable restaurantTable) {
-        if(tableRepository.findById(restaurantTable.getTableNumber()).isPresent() && id!=restaurantTable.getTableNumber()){
-            throw new TableNumberAlreadyExistsException(restaurantTable.getTableNumber());
-        }
-        return tableRepository.findById(id).map(existingTable -> {
-            if (restaurantTable.getTableNumber() != null) {
-                existingTable.setTableNumber(restaurantTable.getTableNumber());
-            }
-            if (restaurantTable.getSeatCapacity() != null) {
-                existingTable.setSeatCapacity(restaurantTable.getSeatCapacity());
-            }
-            return tableRepository.save(existingTable);
-        }).orElseThrow(()->new TableNotFoundException(id));
-    }
-
-    @Override
-    public void deleteTable(Integer id) {
-        tableRepository.deleteById(id);
-    }
-
-
-    @Override
-    public List<RestaurantTable> getAllBySeatCapacity(Integer seatCapacity) {
-        return tableRepository.findAllBySeatCapacity(seatCapacity);
-    }
-
-    @Override
-    public RestaurantTable createTable(RestaurantTable restaurantTable) {
-        if(tableRepository.findById(restaurantTable.getTableNumber()).isPresent()){
-            throw new TableNumberAlreadyExistsException(restaurantTable.getTableNumber());
-        }
-        return tableRepository.save(restaurantTable);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/service/impl/ShiftServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/service/impl/ShiftServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,79 +1,0 @@
-package finki.db.tasty_tabs.service.impl;
-
-import finki.db.tasty_tabs.entity.Assignment;
-import finki.db.tasty_tabs.entity.Employee;
-import finki.db.tasty_tabs.entity.Manager;
-import finki.db.tasty_tabs.entity.Shift;
-import finki.db.tasty_tabs.entity.exceptions.ShiftNotFoundException;
-import finki.db.tasty_tabs.repository.AssignmentRepository;
-import finki.db.tasty_tabs.repository.EmployeeRepository;
-import finki.db.tasty_tabs.repository.ManagerRepository;
-import finki.db.tasty_tabs.repository.ShiftRepository;
-import finki.db.tasty_tabs.service.ShiftService;
-import finki.db.tasty_tabs.web.dto.AssignmentDto;
-import finki.db.tasty_tabs.web.dto.ClockInRequest;
-import finki.db.tasty_tabs.web.dto.CreateShiftDto;
-import finki.db.tasty_tabs.web.dto.ShiftDto;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import jakarta.persistence.EntityNotFoundException;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Service
-public class ShiftServiceImpl implements ShiftService{
-    private final ShiftRepository shiftRepository;
-    private final ManagerRepository managerRepository;
-
-    public ShiftServiceImpl(ShiftRepository shiftRepository, ManagerRepository managerRepository) {
-        this.shiftRepository = shiftRepository;
-        this.managerRepository = managerRepository;
-    }
-
-    private Manager getManagerByUsername(String username) {
-        return managerRepository.findByEmail(username)
-                .orElseThrow(() -> new AccessDeniedException("Only managers can assign shifts."));
-    }
-
-    @Override
-    public List<Shift> getAllShifts() {
-        return shiftRepository.findAll();
-    }
-
-    @Override
-    public Shift getShiftById(Long id) {
-        return shiftRepository.findById(id)
-                .orElseThrow(() -> new ShiftNotFoundException(id));
-    }
-
-    @Override
-    public Shift createShift(CreateShiftDto dto, String username) {
-        Manager manager = getManagerByUsername(username);
-        Shift shift = new Shift(dto.date(), dto.start(), dto.end(), manager);
-        return shiftRepository.save(shift);
-    }
-
-    @Override
-    public Shift updateShift(Long id, CreateShiftDto dto, String username) {
-        Manager manager = getManagerByUsername(username);
-        Shift shift = getShiftById(id);
-
-        shift.setDate(dto.date());
-        shift.setStart(dto.start());
-        shift.setEnd(dto.end());
-        shift.setManager(manager);
-
-        return shiftRepository.save(shift);
-    }
-
-    @Override
-    public void deleteShift(Long id, String username) {
-        getManagerByUsername(username);
-        if (!shiftRepository.existsById(id)) {
-            throw new ShiftNotFoundException(id);
-        }
-        shiftRepository.deleteById(id);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/utils/JwtProvider.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/utils/JwtProvider.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,36 +1,0 @@
-package finki.db.tasty_tabs.utils;
-
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
-import io.jsonwebtoken.security.Keys;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.util.Date;
-
-@Component
-public class JwtProvider {
-    @Value("${jwt.secret}")
-    private String jwtSecret;
-    @Value("${jwt.expiration}")
-    private long jwtExpiration;
-
-    public String generateToken(String email) {
-        return Jwts.builder()
-                .setSubject(String.valueOf(email)) // Use user ID as the subject
-                .setIssuedAt(new Date()) // Token issue time
-                .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration)) // Token expiration
-                .signWith(Keys.hmacShaKeyFor(jwtSecret.getBytes()), SignatureAlgorithm.HS256) // HMAC-SHA256 signing
-                .compact();
-    }
-
-    public Claims validateToken(String token) {
-        return Jwts.parserBuilder()
-                .setSigningKey(jwtSecret.getBytes())
-                .build()
-                .parseClaimsJws(token)
-                .getBody();
-    }
-}
-
Index: c/main/java/finki/db/tasty_tabs/web/controllers/AssignmentController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/AssignmentController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,110 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-import finki.db.tasty_tabs.entity.Assignment;
-import finki.db.tasty_tabs.service.AssignmentService;
-import finki.db.tasty_tabs.web.dto.AssignmentDto;
-import finki.db.tasty_tabs.web.dto.CreateAssignmentDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.Authentication;
-import org.springframework.web.bind.annotation.*;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/assignments")
-@Tag(name = "Assignment API", description = "Endpoints for managing shift assignments (Manager only)")
-public class AssignmentController {
-
-    private final AssignmentService assignmentService;
-
-    public AssignmentController(AssignmentService assignmentService) {
-        this.assignmentService = assignmentService;
-    }
-
-    @Operation(summary = "Get all assignments")
-    @GetMapping
-    public List<AssignmentDto> getAllAssignments() {
-        return assignmentService.getAllAssignments()
-                .stream()
-                .map(AssignmentDto::fromAssignment)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get assignment by ID")
-    @GetMapping("/{id}")
-    public ResponseEntity<AssignmentDto> getAssignmentById(@PathVariable Long id) {
-        return ResponseEntity.ok(AssignmentDto.fromAssignment(assignmentService.getAssignmentById(id)));
-    }
-
-    @Operation(summary = "Create assignment (Manager only)")
-    @PostMapping
-    public ResponseEntity<AssignmentDto> createAssignment(@RequestBody CreateAssignmentDto dto, Authentication authentication) {
-        try {
-            String managerEmail = authentication.getName();
-            Assignment assignment = assignmentService.createAssignment(dto, managerEmail);
-            return ResponseEntity.status(HttpStatus.CREATED).body(AssignmentDto.fromAssignment(assignment));
-        } catch (SecurityException e) {
-            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
-        }
-    }
-
-    @Operation(summary = "Update assignment (Manager only)")
-    @PutMapping("/{id}")
-    public ResponseEntity<AssignmentDto> updateAssignment(@PathVariable Long id, @RequestBody CreateAssignmentDto dto, Authentication authentication) {
-        try {
-            String managerEmail = authentication.getName();
-            Assignment updated = assignmentService.updateAssignment(id, dto, managerEmail);
-            return ResponseEntity.ok(AssignmentDto.fromAssignment(updated));
-        } catch (SecurityException e) {
-            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
-        }
-    }
-
-    @Operation(summary = "Delete assignment (Manager only)")
-    @DeleteMapping("/{id}")
-    public ResponseEntity<Void> deleteAssignment(@PathVariable Long id, Authentication authentication) {
-        try {
-            String managerEmail = authentication.getName();
-            assignmentService.deleteAssignment(id, managerEmail);
-            return ResponseEntity.noContent().build();
-        } catch (SecurityException e) {
-            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
-        }
-    }
-
-    @Operation(summary = "Employee clocks in their shift")
-    @PostMapping("/{id}/clockin")
-    public ResponseEntity<AssignmentDto> clockInShift(
-            @PathVariable Long id,
-            @RequestParam(required = false) LocalDateTime clockInTime,
-            Authentication authentication) {
-        try {
-            String employeeEmail = authentication.getName();
-            LocalDateTime timeToSet = clockInTime != null ? clockInTime : LocalDateTime.now();
-            Assignment assignment = assignmentService.clockInShift(id, employeeEmail, timeToSet);
-            return ResponseEntity.ok(AssignmentDto.fromAssignment(assignment));
-        } catch (SecurityException e) {
-            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
-        }
-    }
-
-    @Operation(summary = "Employee clocks out their shift")
-    @PostMapping("/{id}/clockout")
-    public ResponseEntity<AssignmentDto> clockOutShift(
-            @PathVariable Long id,
-            @RequestParam(required = false) LocalDateTime clockOutTime,
-            Authentication authentication) {
-        try {
-            String employeeEmail = authentication.getName();
-            LocalDateTime timeToSet = clockOutTime != null ? clockOutTime : LocalDateTime.now();
-            Assignment assignment = assignmentService.clockOutShift(id, employeeEmail, timeToSet);
-            return ResponseEntity.ok(AssignmentDto.fromAssignment(assignment));
-        } catch (SecurityException e) {
-            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
-        }
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/AuthController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/AuthController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,4 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-public class AuthController {
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/CategoryController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/CategoryController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,63 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-import finki.db.tasty_tabs.entity.Category;
-import finki.db.tasty_tabs.service.CategoryService;
-import finki.db.tasty_tabs.web.dto.CategoryDto;
-import finki.db.tasty_tabs.web.dto.CreateCategoryDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/categories")
-@Tag(name = "Category API", description = "Endpoints for managing product categories")
-public class CategoryController {
-
-    private final CategoryService categoryService;
-
-    public CategoryController(CategoryService categoryService) {
-        this.categoryService = categoryService;
-    }
-
-    @Operation(summary = "Get all categories")
-    @GetMapping
-    public ResponseEntity<List<CategoryDto>> findAll() {
-        List<CategoryDto> categories = categoryService.getAllCategories().stream()
-                .map(CategoryDto::from)
-                .collect(Collectors.toList());
-        return ResponseEntity.ok(categories);
-    }
-
-    @Operation(summary = "Get category by ID")
-    @GetMapping("/{id}")
-    public ResponseEntity<CategoryDto> findById(@PathVariable Long id) {
-        Category category = categoryService.findById(id);
-        return ResponseEntity.ok(CategoryDto.from(category));
-    }
-
-    @Operation(summary = "Create category")
-    @PostMapping("/add")
-    public ResponseEntity<CategoryDto> save(@RequestBody CreateCategoryDto createCategoryDto) {
-        Category saved = categoryService.createCategory(createCategoryDto.toCategory());
-        return ResponseEntity.status(HttpStatus.CREATED).body(CategoryDto.from(saved));
-    }
-
-    @Operation(summary = "Update category")
-    @PutMapping("/edit/{id}")
-    public ResponseEntity<CategoryDto> update(@PathVariable Long id, @RequestBody CreateCategoryDto createCategoryDto) {
-        Category updated = categoryService.updateCategory(id, createCategoryDto.toCategory());
-        return ResponseEntity.ok(CategoryDto.from(updated));
-    }
-
-    @Operation(summary = "Delete category")
-    @DeleteMapping("/delete/{id}")
-    public ResponseEntity<Void> deleteById(@PathVariable Long id) {
-        categoryService.deleteCategory(id);
-        return ResponseEntity.noContent().build();
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/EmployeeController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/EmployeeController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,28 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-import finki.db.tasty_tabs.entity.Employee;
-import finki.db.tasty_tabs.service.EmployeeService;
-import finki.db.tasty_tabs.web.dto.CreateEmployeeRequest;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-@RestController
-@RequestMapping("/api/employees") // New Controller
-class EmployeeController {
-
-    private final EmployeeService employeeService;
-
-    public EmployeeController(EmployeeService employeeService) {
-        this.employeeService = employeeService;
-    }
-
-    // This endpoint would be secured in a real application to ensure only managers can access it.
-    @PostMapping("/manager/create")
-    @PreAuthorize("hasRole('MANAGER')")
-    public ResponseEntity<Employee> createEmployee(@RequestBody CreateEmployeeRequest request) {
-        Employee newEmployee = employeeService.createEmployee(request);
-        return ResponseEntity.status(HttpStatus.CREATED).body(newEmployee);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/OrderController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/OrderController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,189 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-import finki.db.tasty_tabs.entity.Order;
-import finki.db.tasty_tabs.service.OrderService;
-import finki.db.tasty_tabs.web.dto.CreateOrderDto;
-import finki.db.tasty_tabs.web.dto.CreateOrderItemDto;
-import finki.db.tasty_tabs.web.dto.OrderDto;
-import finki.db.tasty_tabs.web.dto.OrderItemDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import org.springframework.format.annotation.DateTimeFormat;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.Authentication;
-import org.springframework.web.bind.annotation.*;
-
-import java.time.LocalDate;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/orders")
-@Tag(name = "Order API", description = "Endpoints for managing orders")
-@RequiredArgsConstructor
-public class OrderController {
-
-    private final OrderService orderService;
-
-    @Operation(summary = "Get all orders (both online and tab)")
-    @GetMapping
-    public List<OrderDto> getAllOrders() {
-        return orderService.findAll().stream()
-                .map(OrderDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get any order by ID")
-    @GetMapping("/{id}")
-    public ResponseEntity<OrderDto> getOrderById(@PathVariable Long id) {
-        return ResponseEntity.ok(OrderDto.from(orderService.findById(id)));
-    }
-
-    @Operation(summary = "Update an existing order")
-    @PutMapping("/{id}")
-    public ResponseEntity<OrderDto> updateOrder(@PathVariable Long id, @RequestBody CreateOrderDto dto) {
-        return ResponseEntity.ok(OrderDto.from(orderService.updateOrder(id, dto)));
-    }
-
-    @Operation(summary = "Delete an order by ID")
-    @DeleteMapping("/{id}")
-    public ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
-        orderService.deleteOrder(id);
-        return ResponseEntity.noContent().build();
-    }
-
-    @Operation(summary = "Calculate total price of an order")
-    @GetMapping("/{id}/total-price")
-    public ResponseEntity<Double> calculateTotalPrice(@PathVariable Long id) {
-        return ResponseEntity.ok(orderService.calculateTotalPrice(id));
-    }
-
-    @Operation(summary = "Update the status of an order")
-    @PatchMapping("/{id}/status")
-    public ResponseEntity<Void> updateOrderStatus(@PathVariable Long id, @RequestBody String status) {
-        orderService.updateOrderStatus(id, status);
-        return ResponseEntity.noContent().build();
-    }
-
-    @Operation(summary = "Cancel an order")
-    @PatchMapping("/{orderId}/cancel")
-    public ResponseEntity<OrderDto> cancelOrder(@PathVariable Long orderId) {
-        return ResponseEntity.ok(OrderDto.from(orderService.cancelOrder(orderId)));
-    }
-
-    // Order Item Endpoints
-    @Operation(summary = "Add an item to an existing order")
-    @PostMapping("/{orderId}/items")
-    public ResponseEntity<OrderItemDto> addItemToOrder(@PathVariable Long orderId, @RequestBody CreateOrderItemDto itemDto) {
-        return ResponseEntity.ok(OrderItemDto.from(orderService.addItemToOrder(orderId, itemDto)));
-    }
-
-    @Operation(summary = "Decrease the quantity of a specific order item")
-    @DeleteMapping("/items/{orderItemId}")
-    public ResponseEntity<Void> decreaseOrderItemQuantity(@PathVariable Long orderItemId) {
-        orderService.decreaseOrderItemQuantity(orderItemId);
-        return ResponseEntity.noContent().build();
-    }
-
-    @Operation(summary = "Update an existing order item")
-    @PutMapping("/items/{orderItemId}")
-    public ResponseEntity<OrderItemDto> updateOrderItem(@PathVariable Long orderItemId, @RequestBody CreateOrderItemDto itemDto) {
-        return ResponseEntity.ok(OrderItemDto.from(orderService.updateOrderItem(orderItemId, itemDto)));
-    }
-
-    @Operation(summary = "Delete an order item by ID")
-    @DeleteMapping("/items/{orderItemId}/delete")
-    public ResponseEntity<Void> deleteOrderItem(@PathVariable Long orderItemId) {
-        orderService.deleteOrderItem(orderItemId);
-        return ResponseEntity.noContent().build();
-    }
-
-    @Operation(summary = "Mark an order item as processed")
-    @PatchMapping("/items/{orderItemId}/process")
-    public ResponseEntity<OrderItemDto> processOrderItem(@PathVariable Long orderItemId) {
-        return ResponseEntity.ok(OrderItemDto.from(orderService.processOrderItem(orderItemId)));
-    }
-
-    // Online Order Endpoints
-    @Operation(summary = "Create a new online order for a logged-in customer")
-    @PostMapping("/online")
-    public ResponseEntity<OrderDto> createOnlineOrder(@RequestBody CreateOrderDto dto, Authentication authentication) {
-        String userEmail = authentication.getName();
-        return ResponseEntity.ok(OrderDto.from(orderService.createOnlineOrder(dto, userEmail)));
-    }
-
-    @Operation(summary = "Get all online orders")
-    @GetMapping("/online")
-    public List<OrderDto> getAllOnlineOrders() {
-        return orderService.findAllOnlineOrders().stream()
-                .map(OrderDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get a specific online order by ID")
-    @GetMapping("/online/{id}")
-    public ResponseEntity<OrderDto> getOnlineOrderById(@PathVariable Long id) {
-        return ResponseEntity.ok(OrderDto.from(orderService.findOnlineOrderById(id)));
-    }
-
-    @Operation(summary = "Get all online orders for a specific customer")
-    @GetMapping("/online/customer/{customerId}")
-    public List<OrderDto> getOnlineOrdersByCustomer(@PathVariable Long customerId) {
-        return orderService.findOnlineOrdersByCustomer(customerId).stream()
-                .map(OrderDto::from)
-                .collect(Collectors.toList());
-    }
-
-    // Tab Order Endpoints
-    @Operation(summary = "Create a new tab order for a logged-in front staff member")
-    @PostMapping("/tab")
-    public ResponseEntity<OrderDto> createTabOrder(@RequestBody CreateOrderDto dto, Authentication authentication) {
-        String userEmail = authentication.getName();
-        return ResponseEntity.ok(OrderDto.from(orderService.createTabOrder(dto, userEmail)));
-    }
-
-    @Operation(summary = "Get all tab orders")
-    @GetMapping("/tab")
-    public List<OrderDto> getAllTabOrders() {
-        return orderService.findAllTabOrders().stream()
-                .map(OrderDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get a specific tab order by ID")
-    @GetMapping("/tab/{id}")
-    public ResponseEntity<OrderDto> getTabOrderById(@PathVariable Long id) {
-        return ResponseEntity.ok(OrderDto.from(orderService.findTabOrderById(id)));
-    }
-
-    @Operation(summary = "Get all tab orders for a specific table on a given date (defaults to today)")
-    @GetMapping("/tab/table/{tableNumber}")
-    public List<OrderDto> getTabOrdersByTableAndDate(
-            @PathVariable Integer tableNumber,
-            @RequestParam(required = false, defaultValue = "#{T(java.time.LocalDate).now()}") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
-        return orderService.findTabOrdersByTableAndDate(tableNumber, date).stream()
-                .map(OrderDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Assign a TabOrder to a specific front staff member")
-    @PatchMapping("/tab/{orderId}/assign-staff/{frontStaffId}")
-    public ResponseEntity<OrderDto> assignOrderToStaff(@PathVariable Long orderId, @PathVariable Long frontStaffId) {
-        return ResponseEntity.ok(OrderDto.from(orderService.assignOrderToStaff(orderId, frontStaffId)));
-    }
-    @Operation(summary = "Get all open orders (pending or in-progress)")
-    @GetMapping("/open")
-    public List<OrderDto> getOpenOrders() {
-        return orderService.findOpenOrders().stream()
-                .map(OrderDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get all closed orders (completed, canceled, or delivered)")
-    @GetMapping("/closed")
-    public List<OrderDto> getClosedOrders() {
-        return orderService.findClosedOrders().stream()
-                .map(OrderDto::from)
-                .collect(Collectors.toList());
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/PaymentController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/PaymentController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,61 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-
-import finki.db.tasty_tabs.entity.Payment;
-import finki.db.tasty_tabs.service.PaymentService;
-import finki.db.tasty_tabs.web.dto.CreatePaymentDto;
-import finki.db.tasty_tabs.web.dto.PaymentDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/payments")
-@Tag(name = "Payment API", description = "Endpoints for managing payments")
-@RequiredArgsConstructor
-public class PaymentController {
-
-    private final PaymentService paymentService;
-
-    @Operation(summary = "Create a new payment for an order")
-    @PostMapping
-    public ResponseEntity<PaymentDto> createPayment(@RequestBody CreatePaymentDto dto) {
-        Payment newPayment = paymentService.createPayment(dto);
-        return ResponseEntity.ok(PaymentDto.from(newPayment));
-    }
-
-    @Operation(summary = "Get a payment by its ID")
-    @GetMapping("/{id}")
-    public ResponseEntity<PaymentDto> getPaymentById(@PathVariable Long id) {
-        Payment payment = paymentService.findPaymentById(id);
-        return ResponseEntity.ok(PaymentDto.from(payment));
-    }
-
-    @Operation(summary = "Get a payment by its associated order ID")
-    @GetMapping("/order/{orderId}")
-    public ResponseEntity<PaymentDto> getPaymentByOrderId(@PathVariable Long orderId) {
-        Payment payment = paymentService.findPaymentByOrderId(orderId);
-        return ResponseEntity.ok(PaymentDto.from(payment));
-    }
-
-    @Operation(summary = "Get all payments")
-    @GetMapping
-    public List<PaymentDto> getAllPayments() {
-        return paymentService.findAllPayments().stream()
-                .map(PaymentDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Update an existing payment")
-    @PutMapping("/{id}")
-    public ResponseEntity<PaymentDto> updatePayment(@PathVariable Long id, @RequestBody CreatePaymentDto dto) {
-        Payment updatedPayment = paymentService.updatePayment(id, dto);
-        return ResponseEntity.ok(PaymentDto.from(updatedPayment));
-    }
-
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/ProductController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/ProductController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,70 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-import finki.db.tasty_tabs.entity.Product;
-import finki.db.tasty_tabs.service.ProductService;
-import finki.db.tasty_tabs.web.dto.CreateProductDto;
-import finki.db.tasty_tabs.web.dto.ProductDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/products")
-@Tag(name = "Product API", description = "Endpoints for managing products")
-public class ProductController {
-
-    private final ProductService productService;
-
-    public ProductController(ProductService productService) {
-        this.productService = productService;
-    }
-
-    @Operation(summary = "Get all products")
-    @GetMapping
-    public ResponseEntity<List<ProductDto>> findAll() {
-        List<ProductDto> products = productService.getAllProducts().stream()
-                .map(ProductDto::from)
-                .collect(Collectors.toList());
-        return ResponseEntity.ok(products);
-    }
-
-    @Operation(summary = "Get product by ID")
-    @GetMapping("/{id}")
-    public ResponseEntity<ProductDto> findById(@PathVariable Long id) {
-        return ResponseEntity.ok(ProductDto.from(productService.findById(id)));
-    }
-
-    @Operation(summary = "Search products by name")
-    @GetMapping("/search")
-    public ResponseEntity<List<ProductDto>> findByName(@RequestParam String name) {
-        List<ProductDto> products = productService.getProductsByName(name).stream()
-                .map(ProductDto::from)
-                .collect(Collectors.toList());
-        return ResponseEntity.ok(products);
-    }
-
-    @Operation(summary = "Create new product")
-    @PostMapping("/add")
-    public ResponseEntity<ProductDto> save(@RequestBody CreateProductDto dto) {
-        return ResponseEntity.status(HttpStatus.CREATED).body(ProductDto.from(productService.createProduct(dto)));
-    }
-
-    @Operation(summary = "Update product")
-    @PutMapping("/edit/{id}")
-    public ResponseEntity<ProductDto> update(@PathVariable Long id, @RequestBody CreateProductDto dto) {
-        var updatedProduct = productService.updateProduct(id, dto);
-        return ResponseEntity.ok(ProductDto.from(updatedProduct));
-    }
-
-    @Operation(summary = "Delete product")
-    @DeleteMapping("/delete/{id}")
-    public ResponseEntity<Void> delete(@PathVariable Long id) {
-        productService.deleteProduct(id);
-        return ResponseEntity.noContent().build();
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/ReservationController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/ReservationController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,104 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-import finki.db.tasty_tabs.entity.Reservation;
-import finki.db.tasty_tabs.service.ReservationService;
-import finki.db.tasty_tabs.web.dto.CreateReservationDto;
-import finki.db.tasty_tabs.web.dto.ReservationDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.RequiredArgsConstructor;
-import org.springframework.format.annotation.DateTimeFormat;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.Authentication;
-import org.springframework.web.bind.annotation.*;
-
-import java.time.LocalDate;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/reservations")
-@Tag(name = "Reservation API", description = "Endpoints for managing reservations")
-@RequiredArgsConstructor
-public class ReservationController {
-
-    private final ReservationService reservationService;
-
-    @Operation(summary = "Get all reservations")
-    @GetMapping
-    public List<ReservationDto> getAll() {
-        return reservationService.getAllReservations()
-                .stream()
-                .map(ReservationDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get reservation by ID")
-    @GetMapping("/{id}")
-    public ResponseEntity<ReservationDto> getById(@PathVariable Long id) {
-        return ResponseEntity.ok(ReservationDto.from(reservationService.getReservationById(id)));
-    }
-
-    @Operation(summary = "Create new reservation")
-    @PostMapping("/add")
-    public ResponseEntity<ReservationDto> create(@RequestBody CreateReservationDto dto, Authentication authentication) {
-        String userEmail = authentication.getName();
-        Reservation reservation = reservationService.createReservation(dto, userEmail);
-        return ResponseEntity.ok(ReservationDto.from(reservation));
-    }
-
-    @Operation(summary = "Update reservation")
-    @PutMapping("/edit/{id}")
-    public ResponseEntity<ReservationDto> update(@PathVariable Long id, @RequestBody CreateReservationDto dto, Authentication authentication) {
-        String userEmail = authentication.getName();
-        Reservation reservation = reservationService.updateReservation(id, dto, userEmail);
-        return ResponseEntity.ok(ReservationDto.from(reservation));
-    }
-
-    @Operation(summary = "Delete reservation")
-    @DeleteMapping("/delete/{id}")
-    public ResponseEntity<Void> delete(@PathVariable Long id) {
-        reservationService.deleteReservation(id);
-        return ResponseEntity.noContent().build();
-    }
-
-    @Operation(summary = "Get all reservations made by the logged-in user")
-    @GetMapping("/myReservations")
-    public List<ReservationDto> getMyReservations(Authentication authentication) {
-        String username = authentication.getName();
-        return reservationService.getAllReservationsByUser(username)
-                .stream()
-                .map(ReservationDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Accept a reservation by a front staff member")
-    @PostMapping("/accept/{reservationId}/table/{tableNumber}")
-    public ResponseEntity<ReservationDto> acceptReservation(
-            @PathVariable Long reservationId,
-            @PathVariable Integer tableNumber,
-            Authentication authentication
-    ) {
-        String frontStaffEmail = authentication.getName();
-        reservationService.acceptReservation(reservationId,frontStaffEmail,tableNumber);
-        return ResponseEntity.ok(ReservationDto.from(reservationService.getReservationById(reservationId)));
-    }
-    @Operation(summary = "Get all reservations for today")
-    @GetMapping("/today")
-    public List<ReservationDto> getTodayReservations() {
-        return reservationService.getAllReservationsForToday()
-                .stream()
-                .map(ReservationDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get all reservations for a specific date")
-    @GetMapping("/by-date")
-    public List<ReservationDto> getReservationsByDate(
-            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
-        return reservationService.getAllReservationsForDate(date)
-                .stream()
-                .map(ReservationDto::from)
-                .collect(Collectors.toList());
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/RestaurantTableController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/RestaurantTableController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,65 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-import finki.db.tasty_tabs.entity.RestaurantTable;
-import finki.db.tasty_tabs.service.RestaurantTableService;
-import finki.db.tasty_tabs.web.dto.CreateRestaurantTableDto;
-import finki.db.tasty_tabs.web.dto.RestaurantTableDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.http.HttpStatus;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/tables")
-@Tag(name = "Restaurant Table API", description = "Endpoints for managing restaurant tables")
-public class RestaurantTableController {
-
-    private final RestaurantTableService restaurantTableService;
-
-    public RestaurantTableController(RestaurantTableService restaurantTableService) {
-        this.restaurantTableService = restaurantTableService;
-    }
-
-    @Operation(summary = "Get all tables", description = "Retrieves a list of all restaurant tables.")
-    @GetMapping
-    public List<RestaurantTableDto> findAll() {
-        return restaurantTableService.getAll()
-                .stream()
-                .map(RestaurantTableDto::from)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get a table by table number", description = "Finds a table by its table number.")
-    @GetMapping("/{tableNumber}")
-    public ResponseEntity<RestaurantTableDto> findById(@PathVariable Integer tableNumber) {
-        return ResponseEntity.ok(RestaurantTableDto.from(restaurantTableService.findById(tableNumber)));
-                }
-
-    @Operation(summary = "Add a new table", description = "Creates a new restaurant table.")
-    @PostMapping("/add")
-    public ResponseEntity<RestaurantTableDto> save(@RequestBody CreateRestaurantTableDto dto) {
-        RestaurantTable newTable = restaurantTableService.createTable(dto.toRestaurantTable());
-        return ResponseEntity.status(HttpStatus.CREATED).body(RestaurantTableDto.from(newTable));
-    }
-
-    @Operation(summary = "Update an existing table", description = "Updates a restaurant table by its table number.")
-    @PutMapping("/edit/{tableNumber}")
-    public ResponseEntity<RestaurantTableDto> update(
-            @PathVariable Integer tableNumber,
-            @RequestBody CreateRestaurantTableDto dto
-    ) {
-        RestaurantTable updatedTable = restaurantTableService.updateTable(tableNumber, dto.toRestaurantTable());
-        return ResponseEntity.ok(RestaurantTableDto.from(updatedTable));
-    }
-
-    @Operation(summary = "Delete a table", description = "Deletes a restaurant table by its table number.")
-    @DeleteMapping("/delete/{tableNumber}")
-    public ResponseEntity<Void> deleteById(@PathVariable Integer tableNumber) {
-        restaurantTableService.deleteTable(tableNumber);
-        return ResponseEntity.noContent().build();
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/controllers/ShiftController.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/controllers/ShiftController.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,67 +1,0 @@
-package finki.db.tasty_tabs.web.controllers;
-
-import finki.db.tasty_tabs.entity.Shift;
-import finki.db.tasty_tabs.service.ShiftService;
-import finki.db.tasty_tabs.web.dto.CreateShiftDto;
-import finki.db.tasty_tabs.web.dto.ShiftDto;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.Authentication;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-@RestController
-@RequestMapping("/api/shifts")
-@Tag(name = "Shift API", description = "Endpoints for managing work shifts (Manager only)")
-public class ShiftController {
-
-    private final ShiftService shiftService;
-
-    public ShiftController(ShiftService shiftService) {
-        this.shiftService = shiftService;
-    }
-
-    @Operation(summary = "Get all shifts")
-    @GetMapping
-    public List<ShiftDto> getAllShifts() {
-        return shiftService.getAllShifts()
-                .stream()
-                .map(ShiftDto::fromShift)
-                .collect(Collectors.toList());
-    }
-
-    @Operation(summary = "Get shift by ID")
-    @GetMapping("/{id}")
-    public ResponseEntity<ShiftDto> getShiftById(@PathVariable Long id) {
-        Shift shift = shiftService.getShiftById(id);
-        return ResponseEntity.ok(ShiftDto.fromShift(shift));
-    }
-
-    @Operation(summary = "Create a shift (Manager only)")
-    @PostMapping
-    public ResponseEntity<ShiftDto> createShift(@RequestBody CreateShiftDto dto, Authentication authentication) {
-        String username = authentication.getName();
-        Shift shift = shiftService.createShift(dto, username);
-        return new ResponseEntity<>(ShiftDto.fromShift(shift), HttpStatus.CREATED);
-    }
-
-    @Operation(summary = "Update a shift (Manager only)")
-    @PutMapping("/{id}")
-    public ResponseEntity<ShiftDto> updateShift(@PathVariable Long id, @RequestBody CreateShiftDto dto, Authentication authentication) {
-        String username = authentication.getName();
-        Shift updatedShift = shiftService.updateShift(id, dto, username);
-        return ResponseEntity.ok(ShiftDto.fromShift(updatedShift));
-    }
-
-    @Operation(summary = "Delete a shift (Manager only)")
-    @DeleteMapping("/{id}")
-    public ResponseEntity<Void> deleteShift(@PathVariable Long id, Authentication authentication) {
-        String username = authentication.getName();
-        shiftService.deleteShift(id, username);
-        return ResponseEntity.noContent().build();
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/AssignmentDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/AssignmentDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,25 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.Assignment;
-import finki.db.tasty_tabs.entity.Employee;
-import finki.db.tasty_tabs.entity.Manager;
-
-import java.time.LocalDateTime;
-
-public record AssignmentDto(
-        Long id,
-        LocalDateTime clockInTime,
-        LocalDateTime clockOutTime,
-        ManagerDto manager,
-        EmployeeDto employee
-) {
-    public static AssignmentDto fromAssignment(Assignment assignment) {
-        return new AssignmentDto(
-                assignment.getId(),
-                assignment.getClockInTime(),
-                assignment.getClockOutTime(),
-                ManagerDto.from(assignment.getManager()),
-                EmployeeDto.from(assignment.getEmployee())
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/AuthDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/AuthDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-public record AuthDto (
-        String token,
-        UserDto user
-){
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CategoryDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CategoryDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.Category;
-
-public record CategoryDto(
-        Long id,
-        String name,
-        Boolean isAvailable
-) {
-    public static CategoryDto from(Category category) {
-        return new CategoryDto(category.getId(), category.getName(), category.getIsAvailable());
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/ClockInRequest.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/ClockInRequest.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-
-@Data
-public class ClockInRequest {
-    private Long employeeId;
-    private Long shiftId;
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateAssignmentDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateAssignmentDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,24 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.Assignment;
-import finki.db.tasty_tabs.entity.Employee;
-import finki.db.tasty_tabs.entity.Manager;
-import finki.db.tasty_tabs.entity.Shift;
-
-import java.time.LocalDateTime;
-
-public record CreateAssignmentDto(
-        LocalDateTime clockInTime,
-        LocalDateTime clockOutTime,
-        Long employeeId,
-        Long shiftId
-) {
-    public Assignment toAssignment(Employee employee,Shift shift) {
-        return new Assignment(
-                clockInTime,
-                clockOutTime,
-                employee,
-                shift
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateCategoryDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateCategoryDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.Category;
-
-public record CreateCategoryDto(
-        String name,
-        Boolean isAvailable
-) {
-    public Category toCategory() {
-        return new Category(name, isAvailable);
-    }
-
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateEmployeeRequest.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateEmployeeRequest.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,17 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.EmployeeType;
-
-public record CreateEmployeeRequest(
-        String email,
-        String password,
-        String street,
-        String city,
-        String phoneNumber,
-        Double netSalary,
-        Double grossSalary,
-        EmployeeType employeeType,
-        Long staffRoleId, // Only for FrontStaff/BackStaff
-        Double tipPercent // Only for FrontStaff
-) {
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateOnlineOrderRequest.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateOnlineOrderRequest.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import lombok.Data;
-import java.time.LocalDateTime;
-import java.util.List;
-
-
-@Data
-public class CreateOnlineOrderRequest {
-    private Long customerId;
-    private String deliveryAddress;
-    private List<OrderItemRequest> items;
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateOrderDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import java.util.List;
-
-public record CreateOrderDto(
-        List<CreateOrderItemDto> orderItems,
-        String status,
-        String type, // "online" or "tab"
-        String deliveryAddress, // For OnlineOrder
-        Integer tableNumber // For TabOrder
-) { }
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateOrderItemDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateOrderItemDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-public record CreateOrderItemDto(
-        Long productId,
-        Integer quantity,
-        Double price,
-        Boolean isProcessed
-) { }
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreatePaymentDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreatePaymentDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-public record CreatePaymentDto(
-        Double tipAmount,
-        String paymentType,
-        Double amount,
-        Long orderId
-) {}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateProductDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateProductDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-public record CreateProductDto(
-        String name,
-        Double price,
-        String taxClass,
-        String description,
-        Boolean manageInventory,
-        Long categoryId,
-        Integer quantity,
-        Integer restockLevel
-) {
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateReservationDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateReservationDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,10 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import lombok.Data;
-import java.time.LocalDateTime;
-
-public record CreateReservationDto(
-        Integer stayLength,
-        LocalDateTime datetime,
-        Integer numberOfPeople
-) {
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateRestaurantTableDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateRestaurantTableDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.RestaurantTable;
-
-public record CreateRestaurantTableDto(
-        Integer tableNumber,
-        Integer seatCapacity
-) {
-    public RestaurantTable toRestaurantTable(){
-        return new RestaurantTable(tableNumber,seatCapacity);
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateShiftDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateShiftDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,21 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import finki.db.tasty_tabs.entity.Manager;
-import finki.db.tasty_tabs.entity.Shift;
-import lombok.Data;
-
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-public record CreateShiftDto(
-        LocalDate date,
-        LocalDateTime start,
-        LocalDateTime end
-) {
-    public Shift toShift(Manager manager) {
-        return new Shift(
-                date,
-                start,
-                end
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/CreateTabOrderRequest.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/CreateTabOrderRequest.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,10 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import lombok.Data;
-import java.time.LocalDateTime;
-import java.util.List;
-@Data
-public class CreateTabOrderRequest {
-    private Integer tableNumber;
-    private Long frontStaffId;
-    private List<OrderItemRequest> items;
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/EmployeeDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/EmployeeDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,27 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.Employee;
-
-import java.time.LocalDateTime;
-
-public record EmployeeDto(
-        Long id,
-        String email,
-        String street,
-        String city,
-        String phoneNumber,
-        Double netSalary,
-        Double grossSalary
-) {
-    public static EmployeeDto from(Employee employee) {
-        return new EmployeeDto(
-                employee.getId(),
-                employee.getEmail(),
-                employee.getStreet(),
-                employee.getCity(),
-                employee.getPhoneNumber(),
-                employee.getNetSalary(),
-                employee.getGrossSalary()
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/FrontStaffDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/FrontStaffDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,29 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.FrontStaff;
-
-public record FrontStaffDto(
-        Long id,
-        String email,
-        String street,
-        String city,
-        String phoneNumber,
-        Double netSalary,
-        Double grossSalary,
-        Double tipPercent,
-        String staffRoleName
-) {
-    public static FrontStaffDto from(FrontStaff user) {
-        return new FrontStaffDto(
-                user.getId(),
-                user.getEmail(),
-                user.getStreet(),
-                user.getCity(),
-                user.getPhoneNumber(),
-                user.getNetSalary(),
-                user.getGrossSalary(),
-                user.getTipPercent(),     // Предпоставуваме дека User има tipPercent
-                user.getStaffRole().getName()   // Предпоставуваме дека User има staffRoleName
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/ManagerDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/ManagerDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import finki.db.tasty_tabs.entity.Manager;
-import lombok.Data;
-import java.time.LocalDateTime;
-import java.util.List;
-public record ManagerDto(
-        Long id,
-        String email
-        ){
-    public static ManagerDto from(Manager manager){
-        return new ManagerDto(manager.getId(), manager.getEmail());
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/OrderDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/OrderDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,68 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.OnlineOrder;
-import finki.db.tasty_tabs.entity.Order;
-import finki.db.tasty_tabs.entity.TabOrder;
-
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public record OrderDto(
-        Long id,
-        LocalDateTime timestamp,
-        String status,
-        String type,
-        String customerName,
-        String deliveryAddress,
-        Integer tableNumber,
-        String frontStaffName,
-        List<OrderItemDto> orderItems
-) {
-    public static OrderDto from(Order order) {
-        if (order instanceof OnlineOrder onlineOrder) {
-            return new OrderDto(
-                    onlineOrder.getId(),
-                    onlineOrder.getTimestamp(),
-                    onlineOrder.getStatus(),
-                    "ONLINE",
-                    onlineOrder.getCustomer().getEmail(),
-                    onlineOrder.getDeliveryAddress(),
-                    null,
-                    null,
-                    onlineOrder.getOrderItems().stream()
-                            .map(OrderItemDto::from)
-                            .collect(Collectors.toList())
-            );
-        } else if (order instanceof TabOrder tabOrder) {
-            return new OrderDto(
-                    tabOrder.getId(),
-                    tabOrder.getTimestamp(),
-                    tabOrder.getStatus(),
-                    "TAB",
-                    null,
-                    null,
-                    tabOrder.getRestaurantTable().getTableNumber(),
-                    tabOrder.getFrontStaff().getEmail(),
-                    tabOrder.getOrderItems().stream()
-                            .map(OrderItemDto::from)
-                            .collect(Collectors.toList())
-            );
-        } else {
-            // Handle the base Order entity if needed
-            return new OrderDto(
-                    order.getId(),
-                    order.getTimestamp(),
-                    order.getStatus(),
-                    "base",
-                    null,
-                    null,
-                    null,
-                    null,
-                    order.getOrderItems().stream()
-                            .map(OrderItemDto::from)
-                            .collect(Collectors.toList())
-            );
-        }
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/OrderItemDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/OrderItemDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,27 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-
-import finki.db.tasty_tabs.entity.OrderItem;
-import java.time.LocalDateTime;
-
-public record OrderItemDto(
-        Long id,
-        Integer quantity,
-        Double price,
-        Boolean isProcessed,
-        LocalDateTime timestamp,
-        Long productId,
-        String productName
-) {
-    public static OrderItemDto from(OrderItem orderItem) {
-        return new OrderItemDto(
-                orderItem.getId(),
-                orderItem.getQuantity(),
-                orderItem.getPrice(),
-                orderItem.getIsProcessed(),
-                orderItem.getTimestamp(),
-                orderItem.getProduct().getId(),
-                orderItem.getProduct().getName()
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/OrderItemRequest.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/OrderItemRequest.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import lombok.Data;
-import java.time.LocalDateTime;
-import java.util.List;
-@Data
-public class OrderItemRequest {
-    private Long productId;
-    private int quantity;
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/PaymentDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/PaymentDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,25 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.Payment;
-
-import java.time.LocalDateTime;
-
-public record PaymentDto(
-        Long id,
-        Double tipAmount,
-        LocalDateTime timestamp,
-        String paymentType,
-        Double amount,
-        Long orderId
-) {
-    public static PaymentDto from(Payment payment) {
-        return new PaymentDto(
-                payment.getId(),
-                payment.getTipAmount(),
-                payment.getTimestamp(),
-                payment.getPaymentType(),
-                payment.getAmount(),
-                payment.getOrder().getId()
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/ProductDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/ProductDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,25 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.Product;
-
-public record ProductDto(
-        Long id,
-        String name,
-        Double price,
-        String taxClass,
-        String description,
-        Boolean manageInventory,
-        CategoryDto category
-) {
-    public static ProductDto from(Product product) {
-        return new ProductDto(product.getId(),
-                product.getName(),
-                product.getPrice(),
-                product.getTaxClass(),
-                product.getDescription(),
-                product.getManageInventory(),
-                CategoryDto.from(product.getCategory())
-                );
-    }
-}
-
Index: c/main/java/finki/db/tasty_tabs/web/dto/RegisterRequest.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/RegisterRequest.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,17 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import jakarta.validation.constraints.NotNull;
-import lombok.Data;
-
-@Data
-public class RegisterRequest {
-    @NotNull(message = "Email is required")
-    private String email;
-    @NotNull(message = "Password is required")
-    private String password;
-    private String passwordConfirmation;
-    private String firstName;
-    private String lastName;
-
-
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/ReservationDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/ReservationDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,24 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import finki.db.tasty_tabs.entity.Reservation;
-import lombok.Data;
-import java.time.LocalDateTime;
-import java.util.List;
-public record ReservationDto(
-        Long id,
-        Integer stayLength,
-        LocalDateTime datetime,
-        LocalDateTime creationTimestamp,
-        Integer numberOfPeople,
-        String email
-) {
-    public static ReservationDto from(Reservation reservation) {
-        return new ReservationDto(
-                reservation.getId(),
-                reservation.getStayLength(),
-                reservation.getDatetime(),
-                reservation.getCreationTimestamp(),
-                reservation.getNumberOfPeople(),
-                reservation.getUser().getEmail()
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/RestaurantTableDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/RestaurantTableDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.RestaurantTable;
-
-public record RestaurantTableDto(
-        Integer tableNumber,
-        Integer seatCapacity
-) {
-    public static RestaurantTableDto from(RestaurantTable table){
-        return new RestaurantTableDto(table.getTableNumber(), table.getSeatCapacity());
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/ShiftDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/ShiftDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,29 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import finki.db.tasty_tabs.entity.Manager;
-import finki.db.tasty_tabs.entity.Shift;
-import lombok.Data;
-
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-public record ShiftDto(
-        Long id,
-        LocalDate date,
-        LocalDateTime start,
-        LocalDateTime end,
-        ManagerDto manager,
-        List<AssignmentDto> assignments
-) {
-    public static ShiftDto fromShift(Shift shift) {
-        return new ShiftDto(
-                shift.getId(),
-                shift.getDate(),
-                shift.getStart(),
-                shift.getEnd(),
-                ManagerDto.from(shift.getManager()),
-                shift.getAssignments().stream()
-                        .map(AssignmentDto::fromAssignment)
-                        .toList()
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/TransferTabRequest.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/TransferTabRequest.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-import lombok.Data;
-import java.time.LocalDateTime;
-import java.util.List;
-@Data
-public class TransferTabRequest {
-    private Long newFrontStaffId;
-}
Index: c/main/java/finki/db/tasty_tabs/web/dto/UserDto.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/dto/UserDto.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,21 +1,0 @@
-package finki.db.tasty_tabs.web.dto;
-
-import finki.db.tasty_tabs.entity.User;
-
-public record UserDto(
-        Long id,
-        String email,
-        String street,
-        String city,
-        String phoneNumber
-) {
-    public static UserDto from(User user) {
-        return new UserDto(
-                user.getId(),
-                user.getEmail(),
-                user.getStreet(),
-                user.getCity(),
-                user.getPhoneNumber()
-        );
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/exception/FilterExceptionHandler.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/exception/FilterExceptionHandler.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,75 +1,0 @@
-package finki.db.tasty_tabs.web.exception;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import io.jsonwebtoken.ExpiredJwtException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.HttpStatusCode;
-import org.springframework.http.ProblemDetail;
-import org.springframework.security.authentication.AccountStatusException;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authorization.AuthorizationDeniedException;
-
-import java.io.IOException;
-import java.net.URI;
-import java.nio.file.AccessDeniedException;
-import java.security.SignatureException;
-
-@Slf4j
-public class FilterExceptionHandler {
-
-    // Handle an exception within a filter using the same ErrorResponse structure.
-    public static void handleException(HttpServletRequest request,
-                                       HttpServletResponse response,
-                                       Exception exception) throws IOException {
-        // Convert exception -> ErrorResponse just like your GlobalExceptionHandler.
-        ProblemDetail errorDetail = createErrorResponse(exception);
-        errorDetail.setInstance(URI.create(request.getRequestURI()));
-
-        // Write the ErrorResponse as JSON to response
-        response.setStatus(errorDetail.getStatus());
-        response.setContentType("application/json");
-
-        // For JSON serialization, you can use Jackson's ObjectMapper if available.
-        String json = new ObjectMapper().writeValueAsString(errorDetail);
-        response.getWriter().write(json);
-        response.getWriter().flush();
-    }
-
-    private static ProblemDetail createErrorResponse(Exception exception) {
-        ProblemDetail detail = null;
-
-        if (exception instanceof BadCredentialsException) {
-            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(401), exception.getMessage());
-            detail.setProperty("description", "The username or password is incorrect");
-        } else if (exception instanceof AccountStatusException) {
-            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            detail.setProperty("description", "The account is locked");
-        } else if (exception instanceof AccessDeniedException) {
-            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            detail.setProperty("description", "You are not authorized to access this resource");
-        } else if (exception instanceof SignatureException) {
-            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            detail.setProperty("description", "The JWT signature is invalid");
-        } else if (exception instanceof ExpiredJwtException) {
-            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(401), exception.getMessage());
-            detail.setProperty("description", "The JWT token has expired");
-        } else if (exception instanceof AuthorizationDeniedException) {
-            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            detail.setProperty("description", "You are not authorized to access this resource");
-        }
-
-        if (detail == null) {
-            // Unknown/unhandled exception
-            detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
-            detail.setProperty("description", "Unknown internal server error.");
-        }
-
-//        log.warn("An exception occurred: {}", exception.getMessage(), exception);
-
-        return detail;
-    }
-}
-
-
Index: c/main/java/finki/db/tasty_tabs/web/exception/GlobalExceptionHandler.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/exception/GlobalExceptionHandler.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,100 +1,0 @@
-package finki.db.tasty_tabs.web.exception;
-
-import finki.db.tasty_tabs.entity.exceptions.DomainException;
-import io.jsonwebtoken.ExpiredJwtException;
-import io.jsonwebtoken.JwtException;
-import io.jsonwebtoken.security.SignatureException;
-import io.swagger.v3.oas.annotations.Hidden;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.HttpStatusCode;
-import org.springframework.http.ProblemDetail;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.authentication.AccountStatusException;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authorization.AuthorizationDeniedException;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-
-@RestControllerAdvice
-@Hidden
-@Slf4j
-public class GlobalExceptionHandler {
-
-    @ExceptionHandler({JwtException.class, AuthenticationException.class, SignatureException.class, AccessDeniedException.class})
-    public ProblemDetail handleSecurityExceptions(Exception exception) {
-        ProblemDetail errorDetail = null;
-
-//        log.warn("Security exception: {}", exception.getMessage());
-        if (exception instanceof BadCredentialsException) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(401), exception.getMessage());
-            errorDetail.setProperty("description", "The username or password is incorrect");
-
-        }
-        if (exception instanceof IllegalStateException) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(400), exception.getMessage());
-            errorDetail.setProperty("description", "Invalid operation: " + exception.getMessage());
-        }
-
-        if (exception instanceof AccountStatusException) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            errorDetail.setProperty("description", "The account is locked");
-        }
-
-        if (exception instanceof AuthorizationDeniedException){
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            errorDetail.setProperty("description", "You are not authorized to access this resource");
-        }
-
-        if (exception instanceof AccessDeniedException) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            errorDetail.setProperty("description", "You are not authorized to access this resource");
-        }
-        if (exception instanceof SecurityException) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            errorDetail.setProperty("description", "You are not authorized to perform this action");
-        }
-
-        if (exception instanceof SignatureException) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            errorDetail.setProperty("description", "The JWT signature is invalid");
-        }
-
-        if (exception instanceof ExpiredJwtException) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(403), exception.getMessage());
-            errorDetail.setProperty("description", "The JWT token has expired");
-        }
-
-        if (errorDetail == null) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
-            errorDetail.setProperty("description", "Unknown internal server error.");
-        }
-
-        return errorDetail;
-    }
-
-    @ExceptionHandler(DomainException.class)
-    public ProblemDetail handleDomainExceptions(DomainException exception) {
-        ProblemDetail errorDetail = null;
-
-//        log.warn("Domain exception: {}", exception.getMessage());
-
-        if (errorDetail == null) {
-            errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
-            errorDetail.setProperty("description", "Unknown internal server error.");
-        }
-
-        return errorDetail;
-    }
-
-
-    @ExceptionHandler(Exception.class)
-    public ProblemDetail handleAllExceptions(Exception exception) {
-        ProblemDetail errorDetail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), exception.getMessage());
-        errorDetail.setProperty("description", "Unknown internal server error.");
-
-//        log.error("Unexpected exception: {}", exception.getMessage(), exception);
-
-        return errorDetail;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/filter/HttpLoggingFilter.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/filter/HttpLoggingFilter.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,59 +1,0 @@
-package finki.db.tasty_tabs.web.filter;
-
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.MDC;
-import org.springframework.security.authentication.AnonymousAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import java.io.IOException;
-
-@Component
-@Slf4j
-public class HttpLoggingFilter extends OncePerRequestFilter {
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest req,
-                                    HttpServletResponse resp,
-                                    FilterChain chain)
-            throws ServletException, IOException {
-
-        long start = System.currentTimeMillis();
-        try {
-            chain.doFilter(req, resp);
-        } finally {
-            MDC.put("userId", resolveUserId());
-
-            // — compute duration —
-            long timeMs = System.currentTimeMillis() - start;
-            MDC.put("timeMs", String.valueOf(timeMs));
-
-            // — log it —
-//            log.info("Request: {} {} {} from {} – {}ms",
-//                    resp.getStatus(),
-//                    req.getMethod(),
-//                    req.getRequestURI(),
-//                    req.getRemoteAddr(),
-//                    timeMs);
-
-            // — cleanup —
-            MDC.clear();
-        }
-    }
-
-    private String resolveUserId() {
-        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-        if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
-            return "ANONYMOUS";
-        }
-        return ((UserDetails) authentication.getPrincipal()).getUsername();
-    }
-}
-
Index: c/main/java/finki/db/tasty_tabs/web/filter/JwtAuthenticationFilter.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/filter/JwtAuthenticationFilter.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,89 +1,0 @@
-package finki.db.tasty_tabs.web.filter;
-
-import finki.db.tasty_tabs.utils.JwtProvider;
-import finki.db.tasty_tabs.web.exception.FilterExceptionHandler;
-import finki.db.tasty_tabs.web.security.CustomUserDetailsService;
-import finki.db.tasty_tabs.web.security.PublicUrlProvider;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.ExpiredJwtException;
-import io.jsonwebtoken.JwtException;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authorization.AuthorizationDeniedException;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
-import org.springframework.stereotype.Component;
-import org.springframework.util.AntPathMatcher;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import java.io.IOException;
-
-@Component
-@Slf4j
-public class JwtAuthenticationFilter extends OncePerRequestFilter {
-    private final JwtProvider jwtProvider;
-    private final CustomUserDetailsService userDetailsService;
-    private final PublicUrlProvider publicUrlProvider;
-    private final AntPathMatcher pathMatcher = new AntPathMatcher();
-
-    // Update the constructor
-    public JwtAuthenticationFilter(JwtProvider jwtProvider, CustomUserDetailsService userDetailsService, PublicUrlProvider publicUrlProvider) {
-        this.jwtProvider = jwtProvider;
-        this.userDetailsService = userDetailsService;
-        this.publicUrlProvider = publicUrlProvider;
-    }
-
-    // --- NEW METHOD ---
-    @Override
-    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
-        // This method tells Spring to SKIP this filter entirely if the path matches.
-        return publicUrlProvider.getPublicPaths().stream()
-                .anyMatch(p -> pathMatcher.match(p, request.getServletPath()));
-    }
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request,
-                                    HttpServletResponse response,
-                                    FilterChain filterChain) throws ServletException, IOException {
-        try {
-            String token = resolveToken(request);
-            Claims claims = jwtProvider.validateToken(token);
-            if (claims != null) {
-                String userId = claims.getSubject();
-                UserDetails userDetails = userDetailsService.loadUserByUserId(Long.parseLong(userId));
-
-                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
-                        userDetails, null, userDetails.getAuthorities());
-                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
-
-                SecurityContextHolder.getContext().setAuthentication(authentication);
-//                log.debug("JWT token validated");
-            }
-            filterChain.doFilter(request, response);
-        } catch (ExpiredJwtException e) {
-//            log.debug("JWT token expired: {}", e.getMessage());
-            FilterExceptionHandler.handleException(request, response, e);
-        } catch (AuthorizationDeniedException e) {
-//            log.debug("Authorization denied: {}", e.getMessage());
-            FilterExceptionHandler.handleException(request, response, e);
-        } catch (JwtException e) {
-//            log.debug("JWT token invalid: {}", e.getMessage());
-            filterChain.doFilter(request, response);
-        } catch (Exception e) {
-            FilterExceptionHandler.handleException(request, response, e);
-        }
-    }
-
-    private String resolveToken(HttpServletRequest request) {
-        String bearerToken = request.getHeader("Authorization");
-        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
-            return bearerToken.substring(7);
-        }
-        return null;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/security/CustomUserDetailsService.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/security/CustomUserDetailsService.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package finki.db.tasty_tabs.web.security;
-
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-
-public interface CustomUserDetailsService extends UserDetailsService {
-    UserDetails loadUserByUserId(Long userId);
-}
Index: c/main/java/finki/db/tasty_tabs/web/security/PublicUrlProvider.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/security/PublicUrlProvider.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,20 +1,0 @@
-package finki.db.tasty_tabs.web.security;
-
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-@Component
-public class PublicUrlProvider {
-    // This list should exactly match the permitAll() paths in your SecurityConfig
-    private static final List<String> PUBLIC_PATHS = List.of(
-            "/swagger-ui/**",
-            "/v3/api-docs/**",
-            "/api/categories/**",
-            "/api/**"
-    );
-
-    public List<String> getPublicPaths() {
-        return PUBLIC_PATHS;
-    }
-}
Index: c/main/java/finki/db/tasty_tabs/web/security/SecurityConfig.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/security/SecurityConfig.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,71 +1,0 @@
-package finki.db.tasty_tabs.web.security;
-
-import finki.db.tasty_tabs.web.filter.JwtAuthenticationFilter;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpMethod;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
-import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.security.web.SecurityFilterChain;
-import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.CorsConfigurationSource;
-import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-
-import java.util.Arrays;
-import java.util.List;
-
-@Configuration
-@EnableWebSecurity
-@EnableMethodSecurity
-public class SecurityConfig {
-    @Autowired
-    private JwtAuthenticationFilter jwtAuthenticationFilter;
-
-    @Bean
-    public SecurityFilterChain securityFilterChain(HttpSecurity http, PublicUrlProvider publicUrlProvider) throws Exception {
-        http
-                .csrf(AbstractHttpConfigurer::disable)
-                .cors(cors -> cors.configurationSource(corsConfigurationSource())) // Enable CORS
-                .authorizeHttpRequests(authorize -> authorize
-                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
-                        .requestMatchers(publicUrlProvider.getPublicPaths().toArray(new String[0])).permitAll()
-                        .anyRequest().authenticated()
-                )
-                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
-
-        return http.build();
-    }
-
-    @Bean
-    public CorsConfigurationSource corsConfigurationSource() {
-        CorsConfiguration config = new CorsConfiguration();
-        config.setAllowedOrigins(List.of("*")); // Or specific origins
-        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
-        config.setAllowedHeaders(List.of("*"));
-        config.setAllowCredentials(false);
-        config.setMaxAge(3600L);
-
-        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
-        source.registerCorsConfiguration("/**", config);
-        return source;
-    }
-
-    @Bean
-    public PasswordEncoder passwordEncoder() {
-        return new BCryptPasswordEncoder();
-    }
-
-    @Bean
-    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
-        return authenticationConfiguration.getAuthenticationManager();
-    }
-
-}
Index: c/main/java/finki/db/tasty_tabs/web/security/UserDetailsServiceImpl.java
===================================================================
--- src/main/java/finki/db/tasty_tabs/web/security/UserDetailsServiceImpl.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,76 +1,0 @@
-package finki.db.tasty_tabs.web.security;
-
-import finki.db.tasty_tabs.entity.*;
-import finki.db.tasty_tabs.repository.UserRepository;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.stereotype.Service;
-
-import java.util.HashSet;
-import java.util.Set;
-
-@Slf4j
-@Service
-public class UserDetailsServiceImpl implements CustomUserDetailsService {
-    @Autowired
-    private UserRepository userRepository;
-
-    @Override
-    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-//        log.debug("Loading user by username: {}", username);
-        User user = userRepository.findByEmail(username)
-                .orElseThrow(() -> new UsernameNotFoundException("User not found with email: " + username));
-
-        return getUserDetails(user);
-    }
-
-    @Override
-    public UserDetails loadUserByUserId(Long userId) {
-        log.debug("Loading user by ID: {}", userId);
-        User user = userRepository.findById(userId)
-                .orElseThrow(() -> new UsernameNotFoundException("User not found with ID: " + userId));
-
-        return getUserDetails(user);
-    }
-
-    private UserDetails getUserDetails(User user){
-
-
-        // Convert roles to Spring Security's authorities
-        Set<GrantedAuthority> authorities = new HashSet<>();
-        GrantedAuthority grantedAuthority = getGrantedAuthority(user);
-
-        authorities.add(grantedAuthority);
-        log.debug("Applying role {} to user {}", grantedAuthority.getAuthority(), user.getId());
-
-        return new org.springframework.security.core.userdetails.User(
-                user.getEmail(),
-                user.getPassword(),
-                authorities
-        );
-    }
-
-    private static GrantedAuthority getGrantedAuthority(User user) {
-        GrantedAuthority grantedAuthority;
-
-        if(user instanceof Employee){
-            if(user instanceof Manager){
-                grantedAuthority = new SimpleGrantedAuthority("ROLE_MANAGER");
-            } else if(user instanceof FrontStaff){
-                grantedAuthority = new SimpleGrantedAuthority("ROLE_FRONT_STAFF");
-            } else if (user instanceof BackStaff){
-                grantedAuthority = new SimpleGrantedAuthority("ROLE_BACKSTAFF");
-            } else {
-                grantedAuthority = new SimpleGrantedAuthority("ROLE_EMPLOYEE");
-            }
-        } else{
-            grantedAuthority = new SimpleGrantedAuthority("ROLE_CUSTOMER");
-        }
-        return grantedAuthority;
-    }
-}
-
Index: c/main/resources/application-test.properties
===================================================================
--- src/main/resources/application-test.properties	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,7 +1,0 @@
-spring.datasource.url=jdbc:postgresql://localhost:5435/spring_boot_db
-spring.datasource.username=springuser
-spring.datasource.password=springpassword
-spring.datasource.driver-class-name=org.postgresql.Driver
-spring.jpa.hibernate.ddl-auto=none
-spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
-spring.flyway.enabled=false
Index: c/main/resources/application.properties
===================================================================
--- src/main/resources/application.properties	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,9 +1,0 @@
-spring.application.name=Tasty Tabs
-#spring.datasource.url=jdbc:postgresql://localhost:5433/your_db
-#spring.datasource.username=your_db_user
-#spring.datasource.password=your_db_password
-spring.profiles.active=test
-springdoc.api-docs.enabled=true
-springdoc.swagger-ui.enabled=true
-jwt.secret=e249a8adbb3572a23f1520e69573aab8bc4b2eaf0bfab9c7a8d118a0c5d799aa
-jwt.expiration=86400000
Index: c/test/java/finki/db/tasty_tabs/TastyTabsApplicationTests.java
===================================================================
--- src/test/java/finki/db/tasty_tabs/TastyTabsApplicationTests.java	(revision 8264e4e52202043995fb45d1146660e8e1ce60ee)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package finki.db.tasty_tabs;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class TastyTabsApplicationTests {
-
-    @Test
-    void contextLoads() {
-    }
-
-}
