From c42bdba54f106c82713647b1e1d82f78b2d9bc9d Mon Sep 17 00:00:00 2001 From: Vincent Chalamon <407859+vincentchalamon@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:54:34 +0200 Subject: [PATCH] fix: ci --- .github/workflows/ci.yml | 2 + api/src/DataFixtures/Story/DefaultStory.php | 14 +-- api/src/Entity/Book.php | 2 +- api/src/Entity/Bookmark.php | 1 + api/tests/Api/BookmarkTest.php | 6 +- api/tests/Serializer/BookNormalizerTest.php | 4 +- .../Processor/BookPersistProcessorTest.php | 4 +- docker-compose.prod.yml | 8 +- helm/api-platform/keycloak/certs/tls.crt | 21 ++++ helm/api-platform/keycloak/certs/tls.pem | 49 +++++++++ pwa/components/book/Filters.tsx | 16 +-- pwa/components/book/List.tsx | 7 +- pwa/components/book/Show.tsx | 20 +++- pwa/components/common/Pagination.tsx | 2 +- pwa/components/review/List.tsx | 4 +- pwa/pages/bookmarks/index.tsx | 4 +- pwa/pages/books/[id]/[slug]/index.tsx | 2 +- pwa/pages/books/index.tsx | 7 +- pwa/tests/BookView.spec.ts | 46 ++++---- pwa/tests/BookmarksList.spec.ts | 32 +++--- pwa/tests/BooksList.spec.ts | 60 +++++----- pwa/tests/User.spec.ts | 19 ++-- .../covers.openlibrary.org/b/id/9157544-L.jpg | Bin 0 -> 61768 bytes .../covers.openlibrary.org/b/id/9157544-M.jpg | Bin 0 -> 21506 bytes .../openlibrary.org/books/OL25840917M.json | 103 ++++++++++++++++++ pwa/tests/pages/AbstractPage.ts | 19 +++- pwa/tests/pages/BookPage.ts | 23 ++-- pwa/tests/pages/BookmarkPage.ts | 6 +- pwa/tests/test.ts | 12 +- 29 files changed, 360 insertions(+), 133 deletions(-) create mode 100644 helm/api-platform/keycloak/certs/tls.crt create mode 100644 helm/api-platform/keycloak/certs/tls.pem create mode 100644 pwa/tests/mocks/covers.openlibrary.org/b/id/9157544-L.jpg create mode 100644 pwa/tests/mocks/covers.openlibrary.org/b/id/9157544-M.jpg create mode 100644 pwa/tests/mocks/openlibrary.org/books/OL25840917M.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8bc66cc29..032a75ee6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,6 +91,8 @@ jobs: POSTGRES_PASSWORD: aae5bf316ef5fe87ad806c6a9240fff68bcfdaf7 KEYCLOAK_POSTGRES_PASSWORD: 26d7f630f1524eb210bbf496443f2038a9316e9e KEYCLOAK_ADMIN_PASSWORD: 2f31e2fad93941b818449fd8d57fd019b6ce7fa5 + KEYCLOAK_HTTPS_CERTIFICATE_FILE: ./helm/api-platform/keycloak/certs/tls.crt + KEYCLOAK_HTTPS_CERTIFICATE_KEY_FILE: ./helm/api-platform/keycloak/certs/tls.pem # https://docs.docker.com/compose/environment-variables/envvars/ COMPOSE_FILE: docker-compose.yml:docker-compose.prod.yml steps: diff --git a/api/src/DataFixtures/Story/DefaultStory.php b/api/src/DataFixtures/Story/DefaultStory.php index c73f551c8..c646d9e92 100644 --- a/api/src/DataFixtures/Story/DefaultStory.php +++ b/api/src/DataFixtures/Story/DefaultStory.php @@ -9,7 +9,6 @@ use App\DataFixtures\Factory\ReviewFactory; use App\DataFixtures\Factory\UserFactory; use App\Enum\BookCondition; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Serializer\Encoder\DecoderInterface; use Zenstruck\Foundry\Story; @@ -24,7 +23,7 @@ public function build(): void // Create default book (must be created first to appear first in list) $defaultBook = BookFactory::createOne([ 'condition' => BookCondition::UsedCondition, - 'book' => 'https://openlibrary.org/books/OL17267881W.json', + 'book' => 'https://openlibrary.org/books/OL25840917M.json', 'title' => 'The Three-Body Problem', 'author' => 'Liu Cixin', ]); @@ -75,6 +74,7 @@ public function build(): void BookmarkFactory::createOne([ 'book' => $defaultBook, 'user' => $defaultUser, + 'bookmarkedAt' => \DateTimeImmutable::createFromMutable(BookmarkFactory::faker()->dateTime('-1 hour')), ]); // Default user has bookmarked other books @@ -82,6 +82,7 @@ public function build(): void BookmarkFactory::createOne([ 'user' => $defaultUser, 'book' => $books[$key], + 'bookmarkedAt' => \DateTimeImmutable::createFromMutable(BookmarkFactory::faker()->dateTime('-1 week')), ]); } @@ -93,13 +94,4 @@ public function build(): void 'roles' => ['ROLE_ADMIN'], ]); } - - private function getData(string $uri): array - { - return $this->decoder->decode($this->client->request(Request::METHOD_GET, $uri, [ - 'headers' => [ - 'Accept' => 'application/json', - ], - ])->getContent(), 'json'); - } } diff --git a/api/src/Entity/Book.php b/api/src/Entity/Book.php index 8fee5829e..4c6d0df77 100644 --- a/api/src/Entity/Book.php +++ b/api/src/Entity/Book.php @@ -98,7 +98,7 @@ class Book */ #[ApiProperty( types: ['https://schema.org/itemOffered', 'https://purl.org/dc/terms/BibliographicResource'], - example: 'https://openlibrary.org/books/OL17267881W.json' + example: 'https://openlibrary.org/books/OL25840917M.json' )] #[Assert\NotBlank(allowNull: false)] #[Assert\Url(protocols: ['https'])] diff --git a/api/src/Entity/Bookmark.php b/api/src/Entity/Bookmark.php index 43fa8f64b..b1e98ba20 100644 --- a/api/src/Entity/Bookmark.php +++ b/api/src/Entity/Bookmark.php @@ -29,6 +29,7 @@ */ #[ApiResource( types: ['https://schema.org/BookmarkAction'], + order: ['bookmarkedAt' => 'ASC'], operations: [ new GetCollection(), new Delete( diff --git a/api/tests/Api/BookmarkTest.php b/api/tests/Api/BookmarkTest.php index 7a2e4ed95..fe284d0da 100644 --- a/api/tests/Api/BookmarkTest.php +++ b/api/tests/Api/BookmarkTest.php @@ -75,7 +75,7 @@ public function testAsAUserICanGetACollectionOfMyBookmarksWithoutFilters(): void public function testAsAnonymousICannotCreateABookmark(): void { - $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL17267881W.json']); + $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL25840917M.json']); $this->client->request('POST', '/bookmarks', [ 'json' => [ @@ -123,7 +123,7 @@ public function testAsAUserICannotCreateABookmarkWithInvalidData(): void */ public function testAsAUserICanCreateABookmark(): void { - $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL17267881W.json']); + $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL25840917M.json']); $user = UserFactory::createOne(); self::getMercureHub()->reset(); @@ -164,7 +164,7 @@ public function testAsAUserICanCreateABookmark(): void public function testAsAUserICannotCreateADuplicateBookmark(): void { - $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL17267881W.json']); + $book = BookFactory::createOne(['book' => 'https://openlibrary.org/books/OL25840917M.json']); $user = UserFactory::createOne(); BookmarkFactory::createOne(['book' => $book, 'user' => $user]); self::getMercureHub()->reset(); diff --git a/api/tests/Serializer/BookNormalizerTest.php b/api/tests/Serializer/BookNormalizerTest.php index bc93b1bb3..3e4e6af70 100644 --- a/api/tests/Serializer/BookNormalizerTest.php +++ b/api/tests/Serializer/BookNormalizerTest.php @@ -73,7 +73,7 @@ public function testItNormalizesData(): void ->method('normalize') ->with($expectedObject, null, [BookNormalizer::class => true]) ->willReturn([ - 'book' => 'https://openlibrary.org/books/OL17267881W.json', + 'book' => 'https://openlibrary.org/books/OL25840917M.json', 'title' => 'Foundation', 'author' => 'Liu Cixin', 'condition' => BookCondition::NewCondition->value, @@ -82,7 +82,7 @@ public function testItNormalizesData(): void ]); $this->assertEquals([ - 'book' => 'https://openlibrary.org/books/OL17267881W.json', + 'book' => 'https://openlibrary.org/books/OL25840917M.json', 'title' => 'Foundation', 'author' => 'Liu Cixin', 'condition' => BookCondition::NewCondition->value, diff --git a/api/tests/State/Processor/BookPersistProcessorTest.php b/api/tests/State/Processor/BookPersistProcessorTest.php index 916943c13..8c19e1e37 100644 --- a/api/tests/State/Processor/BookPersistProcessorTest.php +++ b/api/tests/State/Processor/BookPersistProcessorTest.php @@ -34,7 +34,7 @@ protected function setUp(): void $this->responseMock = $this->createMock(ResponseInterface::class); $this->decoderMock = $this->createMock(DecoderInterface::class); $this->objectMock = $this->createMock(Book::class); - $this->objectMock->book = 'https://openlibrary.org/books/OL17267881W.json'; + $this->objectMock->book = 'https://openlibrary.org/books/OL25840917M.json'; $this->operationMock = $this->createMock(Operation::class); $this->processor = new BookPersistProcessor( @@ -56,7 +56,7 @@ public function testItUpdatesBookDataBeforeSaveAndSendMercureUpdates(): void ->method('request') ->withConsecutive( [ - Request::METHOD_GET, 'https://openlibrary.org/books/OL17267881W.json', [ + Request::METHOD_GET, 'https://openlibrary.org/books/OL25840917M.json', [ 'headers' => [ 'Accept' => 'application/json', ], diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index f9978c9ba..cae935930 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -47,5 +47,11 @@ services: keycloak: environment: KEYCLOAK_PRODUCTION: "true" - KEYCLOAK_ENABLE_HTTPS: "false" KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} + KEYCLOAK_ENABLE_HTTPS: "true" + KEYCLOAK_HTTPS_USE_PEM: "true" + KEYCLOAK_HTTPS_CERTIFICATE_FILE: /opt/bitnami/keycloak/certs/tls.crt + KEYCLOAK_HTTPS_CERTIFICATE_KEY_FILE: /opt/bitnami/keycloak/certs/tls.key + volumes: + - ${KEYCLOAK_HTTPS_CERTIFICATE_FILE}:/opt/bitnami/keycloak/certs/tls.crt:ro + - ${KEYCLOAK_HTTPS_CERTIFICATE_KEY_FILE}:/opt/bitnami/keycloak/certs/tls.key:ro diff --git a/helm/api-platform/keycloak/certs/tls.crt b/helm/api-platform/keycloak/certs/tls.crt new file mode 100644 index 000000000..3e6248cab --- /dev/null +++ b/helm/api-platform/keycloak/certs/tls.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUGiIkdQOTG1A7NvXDLig7TVDsymIwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA4MjcxNjM5NTFaFw0yNDA4 +MjYxNjM5NTFaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCvnrhtub8e1nwpRj7a0MDDnlH77BzANSVHLR54kB0x +H4wFCIn7GIRXZsKr4xOH68obhtAFbXu+U6fK6ZkmHqhTtro/nU6eGGZhFK6eSVsg +4Hp07eoQ7oNsRX33nScZfpWo6YnH0yFwiUFM8oQW5rNBOUlJfwVONnPQcdGN6X6o +lmuG2j0devmlKoohoIR/P/TNU/4X+PSvotjt1TyPFOeTWPwYvuOoYMiSFQSFNoRy +c67N4Np88PGL84zl9FjZO9ndGje/CDgm3FJj7gswetNX7+4Ge3Q0121vfsvZ2M6k +GTX6jwEysSyvbI0ewjX04IwuWjz1nXYgc4+XbC7N7pmdAgMBAAGjUzBRMB0GA1Ud +DgQWBBT2Hy1/xksuYgSTATWa/O6aD39wvDAfBgNVHSMEGDAWgBT2Hy1/xksuYgST +ATWa/O6aD39wvDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBF +RDCteKuQ+RTEyzsAzslbPm+S/4T8bI+51Xuy+2ehidJtp0RXBk1VIcG2qG3rQdJF +eTe4QbRZPC2g1CjnbBLkoMDJuGCY9a7b1Bc7pCS8oAfN5V044Uem7ydJuekoMEAR +br95hojGe8RN/YOjOa/U9TazjCTo5JFi1UWg+WKK/r8YrBJJWsU+ORxCNMOaVgFp +286Gqdn+4aQo6bPx3xV0X/ny7Dq5i6FpvQkFopUcNpRUnYg+VpB01mNO6BsuduuG +3nmnDCo77LIOVvBuoRpRLaXsqDc7JbLeE1B9lRp1mbvPhTaDXotUglUIaASegA/d +JwdqphZXvvEVMCufLfoY +-----END CERTIFICATE----- diff --git a/helm/api-platform/keycloak/certs/tls.pem b/helm/api-platform/keycloak/certs/tls.pem new file mode 100644 index 000000000..991af88db --- /dev/null +++ b/helm/api-platform/keycloak/certs/tls.pem @@ -0,0 +1,49 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCvnrhtub8e1nwp +Rj7a0MDDnlH77BzANSVHLR54kB0xH4wFCIn7GIRXZsKr4xOH68obhtAFbXu+U6fK +6ZkmHqhTtro/nU6eGGZhFK6eSVsg4Hp07eoQ7oNsRX33nScZfpWo6YnH0yFwiUFM +8oQW5rNBOUlJfwVONnPQcdGN6X6olmuG2j0devmlKoohoIR/P/TNU/4X+PSvotjt +1TyPFOeTWPwYvuOoYMiSFQSFNoRyc67N4Np88PGL84zl9FjZO9ndGje/CDgm3FJj +7gswetNX7+4Ge3Q0121vfsvZ2M6kGTX6jwEysSyvbI0ewjX04IwuWjz1nXYgc4+X +bC7N7pmdAgMBAAECggEAAKMWtSFLoN/nd4EtyD6UqysZfSQXwi+UOJDgpmtqyBz+ +tZ1VULLeBD5Otl7pgX0WRN2BHoTDatYe9M56+AGJaWnNsw17Zobj0QcTSMUUFvhI +pukX7PVgignZp2TEz5gTRpeImfGm6fsevtZzAjeFmqEE8FryE9LRlhoKVXWBvx2m +ZzrYzSk9I6rVWopTiPQGb3XYfstPByDS72CdqOfs3nNr9IV8G5lCbTEa6Tlqrg+/ +KXPg/P4a5s47kSU+i6bJeBk2jK5WXIVG0dqEbUGko+TGrHqO/zTyZVE+H98HjsJV +XHCc5vuJsPAiMF662w+P76+e61LVwgXfDd1SYR6EJQKBgQDTYmCaLDi7lvBsiYyr +Ra1IY7X2pwSf1ddjda8chXcj7MpiWtw1lEegr7KF+zm113wGhvRrH4Dwvsmmg6hX +wlOQot1J5HTeFfjbPf2j56aFRlQoTK8FCuiv/Om9Cn3o32CfS+66NAQunFQWBbgm +ollwmDrD/MekG5IrApv0axTXvwKBgQDUr+i997uoBm9siUo7XjSD0hs2+4I1xqDT +9MASCzJTFhA7Yf7LEBNZC6Njt5kMmkgCHltwhgeNVnSXw/sQuwUA66HZZRjjfDk+ +ndcNIcMEYVrkZVRlGgLHBkT0OGCrgfZKldSdzYSmvIPlsd1/QPZAC1mXsWgCoQWj +b0lc4S2FowKBgH+fldN/f4FC0EW3hkah+s0J5oLUs+YMpc5W7zK5IgV+oXJgiTOQ +Iu7RJWffFijDwQ3vzQIgMyknB3iRZMIXgXyB2DkUxbqQaX91Hf4njlJI8+ag5cqV +m4clm7mW7A39T8jdf3TMkvnRSLNDILuyqW1he5l4tNBQFSACo0YeoKbhAoGBAMr7 +0+Gx1HwpICBy6tC8ONxyIp0X7o6KMiX32XOfEflv/i/ed8CvZ/e8/sQFjmETwZOc +C2LZ181RbNcHKM8v3jehqwcC0H0TqsKS+5JB3ZCJpaiC+MfAylPOLPLz93bYAwnt +80xjv60uD6ehWCbCBgLbkjcPDpgru2jepiKpmbuHAoGBAMgvOpNpVWvPz/midoPl +zlsy5u5ZUK7sjHpPjgvlPNrqmO24f/W0AEFMlHiWynv6W3azxJ7ZALiAkaUOuFXk +iNDXErb7i/2uQdACU0T9hvpn5xLZcyg38z3J1po5SFnStg8CfgUmdIspDCNDgWgG +lz3V38FIz3rZ+02+VC2kbtUd +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUGiIkdQOTG1A7NvXDLig7TVDsymIwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA4MjcxNjM5NTFaFw0yNDA4 +MjYxNjM5NTFaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCvnrhtub8e1nwpRj7a0MDDnlH77BzANSVHLR54kB0x +H4wFCIn7GIRXZsKr4xOH68obhtAFbXu+U6fK6ZkmHqhTtro/nU6eGGZhFK6eSVsg +4Hp07eoQ7oNsRX33nScZfpWo6YnH0yFwiUFM8oQW5rNBOUlJfwVONnPQcdGN6X6o +lmuG2j0devmlKoohoIR/P/TNU/4X+PSvotjt1TyPFOeTWPwYvuOoYMiSFQSFNoRy +c67N4Np88PGL84zl9FjZO9ndGje/CDgm3FJj7gswetNX7+4Ge3Q0121vfsvZ2M6k +GTX6jwEysSyvbI0ewjX04IwuWjz1nXYgc4+XbC7N7pmdAgMBAAGjUzBRMB0GA1Ud +DgQWBBT2Hy1/xksuYgSTATWa/O6aD39wvDAfBgNVHSMEGDAWgBT2Hy1/xksuYgST +ATWa/O6aD39wvDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBF +RDCteKuQ+RTEyzsAzslbPm+S/4T8bI+51Xuy+2ehidJtp0RXBk1VIcG2qG3rQdJF +eTe4QbRZPC2g1CjnbBLkoMDJuGCY9a7b1Bc7pCS8oAfN5V044Uem7ydJuekoMEAR +br95hojGe8RN/YOjOa/U9TazjCTo5JFi1UWg+WKK/r8YrBJJWsU+ORxCNMOaVgFp +286Gqdn+4aQo6bPx3xV0X/ny7Dq5i6FpvQkFopUcNpRUnYg+VpB01mNO6BsuduuG +3nmnDCo77LIOVvBuoRpRLaXsqDc7JbLeE1B9lRp1mbvPhTaDXotUglUIaASegA/d +JwdqphZXvvEVMCufLfoY +-----END CERTIFICATE----- diff --git a/pwa/components/book/Filters.tsx b/pwa/components/book/Filters.tsx index 36a7dbf69..3f5c511bc 100644 --- a/pwa/components/book/Filters.tsx +++ b/pwa/components/book/Filters.tsx @@ -1,12 +1,12 @@ -import { Formik } from "formik"; -import { type FunctionComponent } from "react"; -import { type UseMutationResult } from "react-query"; -import { debounce, Checkbox, FormControlLabel, FormGroup, TextField, Typography } from "@mui/material"; +import {Formik} from "formik"; +import {type FunctionComponent} from "react"; +import {type UseMutationResult} from "react-query"; +import {Checkbox, debounce, FormControlLabel, FormGroup, TextField, Typography} from "@mui/material"; -import { type FiltersProps } from "@/utils/book"; -import { type FetchError, type FetchResponse } from "@/utils/dataAccess"; -import { type PagedCollection } from "@/types/collection"; -import { type Book } from "@/types/Book"; +import {type FiltersProps} from "@/utils/book"; +import {type FetchError, type FetchResponse} from "@/utils/dataAccess"; +import {type PagedCollection} from "@/types/collection"; +import {type Book} from "@/types/Book"; interface Props { filters: FiltersProps | undefined; diff --git a/pwa/components/book/List.tsx b/pwa/components/book/List.tsx index 0ca373e90..6dabfb958 100644 --- a/pwa/components/book/List.tsx +++ b/pwa/components/book/List.tsx @@ -3,7 +3,7 @@ import Head from "next/head"; import { useRouter } from "next/router"; import { useMutation } from "react-query"; import FilterListOutlinedIcon from "@mui/icons-material/FilterListOutlined"; -import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; +import { MenuItem, Select } from "@mui/material"; import { Item } from "@/components/book/Item"; import { Filters } from "@/components/book/Filters"; @@ -18,11 +18,12 @@ interface Props { data: PagedCollection | null; hubURL: string | null; filters: FiltersProps; + page: number; } const getPagePath = (page: number): string => `/books?page=${page}`; -export const List: NextPage = ({ data, hubURL, filters }) => { +export const List: NextPage = ({ data, hubURL, filters, page }) => { const collection = useMercure(data, hubURL); const router = useRouter(); @@ -76,7 +77,7 @@ export const List: NextPage = ({ data, hubURL, filters }) => { ))} - + ) || (

No books found.

diff --git a/pwa/components/book/Show.tsx b/pwa/components/book/Show.tsx index 2fe54093c..a19dde69a 100644 --- a/pwa/components/book/Show.tsx +++ b/pwa/components/book/Show.tsx @@ -50,18 +50,26 @@ export const Show: NextPage = ({ data, hubURL, page }) => { Error | FetchError, BookmarkProps // @ts-ignore - >((data: BookmarkProps) => { + >(async (data: BookmarkProps) => { // @ts-ignore if (!session || session?.error === "RefreshAccessTokenError") return signIn("keycloak"); - // @ts-ignore - if (bookmark) return deleteBookmark(bookmark["@id"]); + if (bookmark) { + // @ts-ignore + deleteBookmark(bookmark["@id"]); + setBookmark(undefined); + + return; + } - return saveBookmark(data); + const response: FetchResponse | undefined = await saveBookmark(data); + if (response && response?.data) { + setBookmark(response.data); + } }); useEffect(() => { - if (status === "loading") return; + if (status === "loading" || status === "unauthenticated") return; (async () => { try { @@ -126,7 +134,7 @@ export const Show: NextPage = ({ data, hubURL, page }) => { {book["description"] ?? "This book has no description."}