sneakers routes

This commit is contained in:
1billy17 2025-06-09 18:06:54 +03:00
parent e360cab7b0
commit 1f9ddbe883
12 changed files with 237 additions and 0 deletions

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>

View File

@ -6,6 +6,7 @@ import io.ktor.server.netty.Netty
import io.ktor.server.routing.route import io.ktor.server.routing.route
import org.example.auth.authRoutes import org.example.auth.authRoutes
import io.ktor.server.routing.routing import io.ktor.server.routing.routing
import org.example.auth.sneakerRoutes
fun main() { fun main() {
embeddedServer(Netty, port = 8080, host = "localhost") { embeddedServer(Netty, port = 8080, host = "localhost") {
@ -19,6 +20,7 @@ fun Application.configureRouting() {
routing { routing {
route("/api") { route("/api") {
authRoutes() authRoutes()
sneakerRoutes()
} }
} }
} }

View File

@ -0,0 +1,96 @@
package org.example.auth
import io.ktor.server.routing.Route
import io.ktor.server.routing.route
import org.example.data.DataRepository
import io.ktor.server.application.*
import io.ktor.server.auth.authenticate
import io.ktor.server.auth.jwt.JWTPrincipal
import io.ktor.server.auth.principal
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import org.example.dto.requests.AddToCartRequest
import org.example.dto.responses.CartResponse
import org.example.dto.responses.FavoritesResponse
import org.example.dto.responses.OperationResponse
import org.example.dto.responses.SneakerResponse
fun Route.sneakerRoutes() {
route("/sneakers") {
get {
val sneakers = DataRepository.getAllSneakers()
call.respond(SneakerResponse(sneakers))
}
authenticate {
route("/favorites") {
get {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("userId")?.asInt()
?: throw IllegalArgumentException("Invalid user")
val favoriteIds = DataRepository.getFavorites(userId)
val sneakers = favoriteIds.mapNotNull { DataRepository.getSneakerById(it) }
call.respond(FavoritesResponse(favoriteIds, sneakers))
}
post {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("userId")?.asInt()
?: throw IllegalArgumentException("Invalid user")
val sneakerId = call.request.queryParameters["sneakerId"]?.toIntOrNull()
?: throw IllegalArgumentException("Missing sneakerId")
val success = DataRepository.addToFavorites(userId, sneakerId)
call.respond(
OperationResponse(
success,
if (success) "Added to favorites" else "Failed to add to favorites"
)
)
}
delete {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("userId")?.asInt()
?: throw IllegalArgumentException("Invalid user")
val sneakerId = call.request.queryParameters["sneakerId"]?.toIntOrNull()
?: throw IllegalArgumentException("Missing sneakerId")
val success = DataRepository.removeFromFavorites(userId, sneakerId)
call.respond(OperationResponse(success, if (success) "Removed from favorites" else "Failed to remove from favorites"))
}
}
route("/cart") {
get {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("userId")?.asInt()
?: throw IllegalArgumentException("Invalid user")
val cartItems = DataRepository.getCart(userId)
val sneakers = cartItems.mapNotNull { DataRepository.getSneakerById(it.sneakerId) }
call.respond(CartResponse(cartItems, sneakers))
}
post {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("userId")?.asInt()
?: throw IllegalArgumentException("Invalid user")
val request = call.receive<AddToCartRequest>()
val success = DataRepository.addToCart(userId, request.sneakerId, request.quantity)
call.respond(OperationResponse(success, if (success) "Added to cart" else "Failed to add to cart"))
}
delete {
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("userId")?.asInt()
?: throw IllegalArgumentException("Invalid user")
val sneakerId = call.request.queryParameters["sneakerId"]?.toIntOrNull()
?: throw IllegalArgumentException("Missing sneakerId")
val success = DataRepository.removeFromCart(userId, sneakerId)
call.respond(OperationResponse(success, if (success) "Removed from cart" else "Failed to remove from cart"))
}
}
}
}
}

View File

@ -1,8 +1,11 @@
package org.example.data package org.example.data
import org.example.data.Models.CartItem
import org.example.data.Models.Sneaker
import org.example.dto.requests.SignInRequest import org.example.dto.requests.SignInRequest
import org.example.dto.requests.SignUpRequest import org.example.dto.requests.SignUpRequest
import org.example.data.Models.User import org.example.data.Models.User
import org.example.data.Models.UserData
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
object DataRepository { object DataRepository {
@ -10,6 +13,16 @@ object DataRepository {
private val idCounter = AtomicInteger(1) private val idCounter = AtomicInteger(1)
private val passwordResetCodes = mutableMapOf<String, String>() private val passwordResetCodes = mutableMapOf<String, String>()
private val sneakers = mutableListOf(
Sneaker(1, "Nike Air Max", 179.39, "Nike", "outdoor", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSycZAb9c3gwov211CDjqS4n-RHt_4kAqDezw&s"),
Sneaker(2, "Adidas Ultraboost", 169.39, "Adidas", "outdoor", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSycZAb9c3gwov211CDjqS4n-RHt_4kAqDezw&s"),
Sneaker(3, "Puma RS-X", 159.39, "Puma", "tennis", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSycZAb9c3gwov211CDjqS4n-RHt_4kAqDezw&s")
)
private val userData = mutableMapOf<Int, UserData>()
// ауф
fun createUser(request: SignUpRequest): User { fun createUser(request: SignUpRequest): User {
val user = User( val user = User(
id = idCounter.getAndIncrement(), id = idCounter.getAndIncrement(),
@ -60,4 +73,49 @@ object DataRepository {
) )
) )
} }
// кросовка
fun getAllSneakers(): List<Sneaker> = sneakers.toList()
fun getSneakerById(id: Int): Sneaker? = sneakers.find { it.id == id }
fun addToFavorites(userId: Int, sneakerId: Int): Boolean {
val sneaker = getSneakerById(sneakerId) ?: return false
val data = userData.getOrPut(userId) { UserData(userId) }
if (!data.favoriteSneakers.contains(sneakerId)) {
data.favoriteSneakers.add(sneakerId)
return true
}
return false
}
fun removeFromFavorites(userId: Int, sneakerId: Int): Boolean {
return userData[userId]?.favoriteSneakers?.remove(sneakerId) ?: false
}
fun addToCart(userId: Int, sneakerId: Int, quantity: Int = 1): Boolean {
val sneaker = getSneakerById(sneakerId) ?: return false
val data = userData.getOrPut(userId) { UserData(userId) }
val existingItem = data.cartItems.find { it.sneakerId == sneakerId }
if (existingItem != null) {
existingItem.quantity += quantity
} else {
data.cartItems.add(CartItem(sneakerId, quantity))
}
return true
}
fun removeFromCart(userId: Int, sneakerId: Int): Boolean {
return userData[userId]?.cartItems?.removeIf { it.sneakerId == sneakerId } ?: false
}
fun getCart(userId: Int): List<CartItem> {
return userData[userId]?.cartItems?.toList() ?: emptyList()
}
fun getFavorites(userId: Int): List<Int> {
return userData[userId]?.favoriteSneakers?.toList() ?: emptyList()
}
} }

View File

@ -0,0 +1,9 @@
package org.example.data.Models
import kotlinx.serialization.Serializable
@Serializable
data class CartItem(
val sneakerId: Int,
var quantity: Int
)

View File

@ -0,0 +1,13 @@
package org.example.data.Models
import kotlinx.serialization.Serializable
@Serializable
data class Sneaker(
val id: Int,
val name: String,
val price: Double,
val brand: String,
val category: String,
val imageUrl: String
)

View File

@ -0,0 +1,10 @@
package org.example.data.Models
import kotlinx.serialization.Serializable
@Serializable
data class UserData(
val userId: Int,
val favoriteSneakers: MutableList<Int> = mutableListOf(),
val cartItems: MutableList<CartItem> = mutableListOf()
)

View File

@ -0,0 +1,9 @@
package org.example.dto.requests
import kotlinx.serialization.Serializable
@Serializable
data class AddToCartRequest(
val sneakerId: Int,
val quantity: Int = 1
)

View File

@ -0,0 +1,11 @@
package org.example.dto.responses
import kotlinx.serialization.Serializable
import org.example.data.Models.CartItem
import org.example.data.Models.Sneaker
@Serializable
data class CartResponse(
val items: List<CartItem>,
val sneakers: List<Sneaker>
)

View File

@ -0,0 +1,10 @@
package org.example.dto.responses
import kotlinx.serialization.Serializable
import org.example.data.Models.Sneaker
@Serializable
data class FavoritesResponse(
val sneakerIds: List<Int>,
val sneakers: List<Sneaker>
)

View File

@ -0,0 +1,9 @@
package org.example.dto.responses
import kotlinx.serialization.Serializable
@Serializable
data class OperationResponse(
val success: Boolean,
val message: String? = null
)

View File

@ -0,0 +1,9 @@
package org.example.dto.responses
import kotlinx.serialization.Serializable
import org.example.data.Models.Sneaker
@Serializable
data class SneakerResponse(
val sneakers: List<Sneaker>
)