diff --git a/lesson_19/template/style.css b/lesson_19/template/style.css index e69de29bb..be39a0d43 100644 --- a/lesson_19/template/style.css +++ b/lesson_19/template/style.css @@ -0,0 +1,398 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +em { + font-style: normal; +} + +body, html { + margin: 0; + font-family: 'Poppins', 'Montserrat', Arial, sans-serif; + background: #fff; +} + +body { + font-family: 'Poppins', sans-serif; + line-height: 1.6; + background-color: #f8f8f8; + color: #333; +} + +/* Header Styling */ +.header { + background-color: #fff; + padding: 20px 48px; + display: flex; + justify-content: space-between; + align-items: center; + color: #243e90; + box-shadow: 0 2px 10px rgba(0,0,0); + position: fixed; + z-index: 1000; + top: 0; + left: 0; + right: 0; + height: 131px; + min-height: 131px; +} + +.header-logo img { + height: 60px; + width: auto; + object-fit: contain; +} + +.header-top-menu { + display: flex; + gap: 32px; + align-items: center; + margin: 0; + padding: 0; + list-style: none; +} + +.header-top-menu li a { + color: #333; + font-weight: 600; + font-size: 1rem; + transition: all 0.3s ease; + padding: 0.5rem 1rem; + font-family: 'Poppins', Arial, sans-serif; + border-radius: 5px; + text-decoration: none; + position: relative; +} + +.header-top-menu a:hover { + color: #3C3C3C; +} + +.header-top-menu li a:hover, +.header-top-menu li a.active { + color: #000; +} + +.header-top-menu li a.active::after { + content: ""; + position: absolute; + left: 0; + bottom: -2px; + width: 100%; + height: 2px; + background-color: #f58220; +} + +/* Sign Up Button */ +.header-cta .sign-up-button { + display: inline-block; + background: #f58220; + color: #fff; + font-weight: 650; + text-decoration: none; + padding: 10px 20px; + border-radius: 8px; + transition: background 0.3s ease; + font-family: 'Poppins', Arial, sans-serif; + border: none; + cursor: pointer; + outline: none; + box-shadow: 0 2px 8px rgba(36,62,144,0.08); +} + +.header-cta .sign-up-button:hover { + background-color: #d66f18; +} + +.header-top-menu li a::after { + content: ""; + position: absolute; + left: 0; + bottom: -2px; + width: 0%; + height: 2px; + background-color: #f58220; + transition: width 0.3s ease; +} + +.header-top-menu li a:hover { + color: #000; +} + +.header-top-menu li a:hover::after { + width: 100%; +} + +/* Hero Section */ +.hero-section { + position: relative; + height: 700px; + background-size: cover; + background-position: center center; + display: flex; + color: #fff; + align-items: flex-start; + justify-content: flex-start; + background-image: url('/images/hero.jpg'); + width: 100%; + left: 50%; + right: 50%; + margin-left: -50vw; + margin-right: -50vw; + overflow: hidden; + top: 0; + margin-top: 0; +} + +.hero-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.2); + z-index: 1; +} + +.hero-content { + position: relative; + z-index: 2; + max-width: 100vw; + margin-left: 0; + padding-left: 0; + border-radius: 8px; + background-color: rgba(0, 0, 0, 0.3); + box-shadow: 0 4px 15px rgba(0,0,0,0.3); + top: 100px; + transform: none; + left: 0; + width: 980px; + display: flex; + flex-direction: column; + align-items: flex-start; +} + +/* Hero Text Content */ +.hero-title { + font-family: 'Montserrat'; + font-size: 54px; + font-weight: 800; + line-height: 1.1; + color: #fff; + margin-bottom: 24px; + text-align: left; + padding-left: 0; + margin-left: 0; + visibility: visible; + box-sizing: border-box; + margin: 0; + padding-top: 10%; + border: 0; + vertical-align: baseline; + letter-spacing: 0; + -webkit-font-smoothing: antialiased; + width: 55%; +} + +.hero-title .highlight { + font-style: italic; + position: relative; + display: inline-block; + color: #fff; + text-decoration: none; + z-index: 1; + background: none; +} + +.hero-title .highlight::after { + content: ""; + position: absolute; + left: 0; + bottom: 2px; + width: 100%; + height: 17px; + background: #f47d26; + z-index: -1; + width: calc(100% + 6px); + opacity: 1; + pointer-events: none; + user-select: none; +} + +.hero-text { + background-color: #1a3c7e; + padding: 25px; + border-radius: 5px; + font-size: 1.1rem; + line-height: 1.6; + margin-top: 20px; + padding-left: 80px; + font-weight: 400; + max-width: 750px; + color: #fff; +} + +.hero-text span { + font-weight: 700; + color: #f47d26; +} + +/* Programs Section */ +.programs-section { + padding: 48px 0 48px 0; + width: 100vw; + margin-left: -50vw; + left: 50%; + right: 50%; + background: #fff; + position: relative; + padding-top: 140px; + box-shadow: 0 12px 32px rgba(36,62,144,0.10); +} + +.programs-section h2 { + font-size: 34px; + font-weight: 900; + color: #333333; + align-items: left; + text-align: left; + width: 1244px; + margin: 0 auto 32px auto; + font-family: 'Montserrat', 'Poppins', Arial, sans-serif; + z-index: 1; + position: relative; + justify-content: left; +} + +.programs-section h2 .highlight { + font-style: normal; + position: relative; + color: #333; + display: inline-block; +} + +.programs-section h2 .highlight::after { + content: ""; + position: absolute; + left: 0; + bottom: 10%; + width: 100%; + height: 6px; + background-color: #f47d26; + z-index: -1; +} + +/* Programs List and Cards */ +.programs { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 32px; + list-style: none; + padding: 0; + margin: 0; + justify-content: center; + margin-left: 135px; + margin-right: 135px; + width: 1244px; +} + +.program { + padding: 24px 20px; + border-radius: 10px; + width: 610px; + max-width: 100%; + background: none; +} + +.program:hover { + transform: translateY(-5px); + box-shadow: 0 8px 25px rgba(0,0,0,0.15); +} + +.program h3 { + font-size: 22px; + font-family: 'Montserrat', 'Poppins', Arial, sans-serif; + color: #444444; + font-weight: 700; + margin-top: 0; + margin-bottom: 12px; +} + +.program p { + font-size: 18px; + font-family: 'Poppins', 'Montserrat', Arial, sans-serif; + color: #676767; + margin: 0; +} + +.program button, +.program a { + display: inline-block; + background: #fff; + border: 1px solid #000; + padding: 8px 16px; + font-size: 0.9rem; + font-weight: 500; + text-decoration: none; + color: #757373; + border-radius: 4px; + transition: all 0.2s ease; + cursor: pointer; +} + +.program button:hover, +.program a:hover { + border-color: #f58220; + color: #f58220; +} + +/* Footer */ +.footer { + background: #fff; + color: #777777; + text-align: center; + padding: 24px 0 0 0; + font-size: 14px; + font-family: 'Poppins', 'Montserrat', Arial, sans-serif; + margin-top: 48px; + border-radius: 0 0 16px 16px; + height: 142px; + display: flex; + align-items: flex-start; + justify-content: center; +} + +.footer a { + color: #f58220; + text-decoration: none; + font-weight: 500; +} + +.footer a:hover { + text-decoration: underline; +} + +@media (max-width: 600px) { + .header { + flex-direction: column; + gap: 15px; + padding: 20px; + } + + .header-top-menu { + gap: 20px; + } + + .hero-title { + font-size: 18px; + } + + .hero-text { + font-size: 12px; + padding: 12px 6px 12px 16px; + width: 980px; + border-radius: 0; + } +} \ No newline at end of file diff --git a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java index 7efa0b2f8..b5b8e0601 100644 --- a/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java +++ b/lesson_23/api/java/api_app/src/main/java/com/codedifferently/lesson23/web/MediaItemsController.java @@ -9,7 +9,11 @@ import java.util.Set; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @@ -31,4 +35,50 @@ public ResponseEntity getItems() { var response = GetMediaItemsResponse.builder().items(responseItems).build(); return ResponseEntity.ok(response); } -} + + @GetMapping("/items/{id}") + public ResponseEntity getItem(@PathVariable String id) { + Set items = library.search(SearchCriteria.builder().id(id).build()); + + if (items.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + MediaItem item = items.iterator().next(); + MediaItemResponse responseItem = MediaItemResponse.from(item); + return ResponseEntity.ok(responseItem); + } + + @PostMapping("/items") + public ResponseEntity addItem(@RequestBody CreateMediaItemRequest request) { + try { + if (request.getItem() == null) { + var errorResponse = java.util.Map.of("errors", java.util.List.of("Item is required")); + return ResponseEntity.badRequest().body(errorResponse); + } + + MediaItem item = MediaItemRequest.asMediaItem(request.getItem()); + library.addMediaItem(item, librarian); + + MediaItemResponse responseItem = MediaItemResponse.from(item); + var response = CreateMediaItemResponse.builder().item(responseItem).build(); + return ResponseEntity.ok(response); + } catch (Exception e) { + var errorResponse = java.util.Map.of("errors", java.util.List.of("Invalid item data")); + return ResponseEntity.badRequest().body(errorResponse); + } + } + + @DeleteMapping("/items/{id}") + public ResponseEntity deleteItem(@PathVariable String id) { + Set items = library.search(SearchCriteria.builder().id(id).build()); + + if (items.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + MediaItem item = items.iterator().next(); + library.removeMediaItem(item, librarian); + return ResponseEntity.noContent().build(); + } +} \ No newline at end of file