From 5915ead7dc1c17cbe825c0d66d215496bad934e5 Mon Sep 17 00:00:00 2001
From: Your Name <email.com>
Date: Tue, 18 Mar 2025 19:46:43 +0300
Subject: [PATCH] categories

---
 init.sql                            | 31 ++++++++++++++++++++++-------
 src/main/kotlin/Application.kt      |  8 +++++---
 src/main/kotlin/AuthService.kt      | 20 ++++++++++++++++++-
 src/main/kotlin/UserDTO.kt          | 21 +++++++++++++------
 src/main/kotlin/Users.kt            | 11 ++++++++++
 src/main/resources/application.conf |  8 +++++++-
 6 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/init.sql b/init.sql
index 69cd246..0c7fb09 100644
--- a/init.sql
+++ b/init.sql
@@ -7,6 +7,12 @@ CREATE TABLE IF NOT EXISTS users (
     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
 );
 
+CREATE TABLE IF NOT EXISTS categories(
+    id serial PRIMARY KEY,
+    name VARCHAR(255) NOT NULL,
+    description VARCHAR(255) NOT NULL
+);
+
 CREATE TABLE IF NOT EXISTS sneakers(
     id SERIAL PRIMARY KEY,
     name VARCHAR(255) NOT NULL,
@@ -15,14 +21,25 @@ CREATE TABLE IF NOT EXISTS sneakers(
     discount INTEGER NOT NULL CHECK (discount >= 0 AND discount <= 100),
     photo VARCHAR(255) NOT NULL,
     gender CHAR(1) NOT NULL CHECK (gender IN ('M', 'F', 'U')),
-    bootSize INTEGER NOT NULL
+    bootSize INTEGER NOT NULL,
+    categoryid INTEGER NOT NULL,
+    FOREIGN KEY (categoryid) REFERENCES categories(id) ON DELETE CASCADE
 );
 
-INSERT INTO sneakers (name, description, cost, discount, photo, gender, bootSize)
-VALUES ('Adidas', 'fast', 120.50, 10, 'https://i8.amplience.net/i/jpl/jd_619310_a?qlt=92', 'M', 42);
+INSERT INTO categories (name, description)
+VALUES ('tennis', 'for tennis');
 
-INSERT INTO sneakers (name, description, cost, discount, photo, gender, bootSize)
-VALUES ('Nike Air Max', 'Comfortable running shoes', 140, 40, 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRe7ZbQ92u1JD-JgD4Kkhkju83p_uvKelP5jw&s', 'F', 39);
+INSERT INTO categories (name, description)
+VALUES ('outdoor', 'for walking');
 
-INSERT INTO sneakers (name, description, cost, discount, photo, gender, bootSize)
-VALUES ('Puma', 'fast too', 80.12, 80, 'https://img01.ztat.net/article/spp-media-p1/c6ebc4348bd34d9fa4235a82453230fe/3c034c2c43b94d879d41d33d0eb18e14.jpg?imwidth=1800&filter=packshot', 'U', 41);
+INSERT INTO categories (name, description)
+VALUES ('football', 'for football');
+
+INSERT INTO sneakers (name, description, cost, discount, photo, gender, bootSize, categoryid)
+VALUES ('Adidas', 'fast', 120.50, 10, 'https://i8.amplience.net/i/jpl/jd_619310_a?qlt=92', 'M', 42, 3);
+
+INSERT INTO sneakers (name, description, cost, discount, photo, gender, bootSize, categoryid)
+VALUES ('Nike Air Max', 'Comfortable running shoes', 140, 40, 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRe7ZbQ92u1JD-JgD4Kkhkju83p_uvKelP5jw&s', 'F', 39, 2);
+
+INSERT INTO sneakers (name, description, cost, discount, photo, gender, bootSize, categoryid)
+VALUES ('Puma', 'fast too', 80.12, 80, 'https://img01.ztat.net/article/spp-media-p1/c6ebc4348bd34d9fa4235a82453230fe/3c034c2c43b94d879d41d33d0eb18e14.jpg?imwidth=1800&filter=packshot', 'U', 41, 1);
diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt
index caebc71..3afbda5 100644
--- a/src/main/kotlin/Application.kt
+++ b/src/main/kotlin/Application.kt
@@ -158,10 +158,12 @@ fun Application.configureRouting() {
                     log.info("User $userEmail is accessing /mainWindow")
 
                     val sneakers = AuthService.selectSneakers()
-                    if (sneakers.isNotEmpty()) {
-                        call.respond(mapOf("sneakers" to sneakers))
+                    val categories = AuthService.selectCategories()
+
+                    if (sneakers.isNotEmpty() && categories.isNotEmpty()) {
+                        call.respond(SneakerCategoryResponse(sneakers, categories))
                     } else {
-                        call.respond(mapOf("error" to "No sneakers found"))
+                        call.respond(mapOf("error" to "No sneakers or categories found"))
                     }
                 } catch (e: Exception) {
                     log.error("Error fetching sneakers: ${e.message}", e)
diff --git a/src/main/kotlin/AuthService.kt b/src/main/kotlin/AuthService.kt
index bae261b..94e7b80 100644
--- a/src/main/kotlin/AuthService.kt
+++ b/src/main/kotlin/AuthService.kt
@@ -103,7 +103,8 @@ object AuthService {
                         discount = it[Sneakers.discount],
                         photo = it[Sneakers.photo],
                         gender = it[Sneakers.gender],
-                        bootSize = it[Sneakers.bootSize]
+                        bootSize = it[Sneakers.bootSize],
+                        categoryId = it[Sneakers.categoryId]
                     )
                 }
             }
@@ -111,6 +112,23 @@ object AuthService {
             throw RuntimeException("Error selecting sneakers: ${e.message}", e)
         }
     }
+
+
+    fun selectCategories(): List<Category> {
+        try {
+            return transaction {
+                Categories.selectAll().map {
+                    Category(
+                        id = it[Categories.id],
+                        name = it[Categories.name],
+                        description = it[Categories.description],
+                    )
+                }
+            }
+        } catch (e: Exception) {
+            throw RuntimeException("Error selecting categories: ${e.message}", e)
+        }
+    }
 }
 
 
diff --git a/src/main/kotlin/UserDTO.kt b/src/main/kotlin/UserDTO.kt
index 78c37c2..aa8b173 100644
--- a/src/main/kotlin/UserDTO.kt
+++ b/src/main/kotlin/UserDTO.kt
@@ -1,13 +1,8 @@
 package com.example
 
-import com.example.Sneakers.char
-import com.example.Sneakers.decimal
-import com.example.Sneakers.integer
-import com.example.Sneakers.varchar
 import kotlinx.serialization.Contextual
 import kotlinx.serialization.Serializable
 import java.math.BigDecimal
-import java.text.DecimalFormat
 
 @Serializable
 data class UserRegisterRequest(val name: String, val email: String, val password: String)
@@ -31,5 +26,19 @@ data class Sneaker(
     val discount: Int,
     val photo: String,
     val gender: Char,
-    val bootSize: Int
+    val bootSize: Int,
+    val categoryId: Int
 )
+
+@Serializable
+data class Category(
+    val id: Int,
+    val name: String,
+    val description: String
+)
+
+@Serializable
+data class SneakerCategoryResponse(
+    val sneakers: List<Sneaker>,
+    val categories: List<Category>
+)
\ No newline at end of file
diff --git a/src/main/kotlin/Users.kt b/src/main/kotlin/Users.kt
index e808f28..72f9006 100644
--- a/src/main/kotlin/Users.kt
+++ b/src/main/kotlin/Users.kt
@@ -1,6 +1,7 @@
 package com.example
 
 import kotlinx.serialization.Serializable
+import org.jetbrains.exposed.sql.ReferenceOption
 import org.jetbrains.exposed.sql.Table
 import org.jetbrains.exposed.sql.javatime.timestamp
 import java.math.BigDecimal
@@ -26,6 +27,16 @@ object Sneakers : Table("sneakers") {
     val photo = varchar("photo", 255)
     val gender = char("gender")
     val bootSize = integer("bootsize")
+    val categoryId = integer("categoryid")
 
     override val primaryKey = PrimaryKey(id)
 }
+
+
+object Categories : Table("categories") {
+    val id = integer("id").autoIncrement()
+    val name = varchar("name", 255)
+    val description = varchar("description", 255)
+
+    override val primaryKey = PrimaryKey(id)
+}
\ No newline at end of file
diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf
index d9465a4..9ac43d3 100644
--- a/src/main/resources/application.conf
+++ b/src/main/resources/application.conf
@@ -1,6 +1,12 @@
+ktor {
+    application {
+        modules = [ com.example.ApplicationKt.main ]
+    }
+}
+
 jwt {
     secret = "secret"
     issue = "http://localhost:8080"
-    audience = "http://localhost:8080/test"  // временная строка
+    audience = "http://localhost:8080/mainWindow"  // временная строка
     realm = "Access to 'hello'"
 }
\ No newline at end of file