├── .gitignore ├── .npmrc ├── .nvmrc ├── LICENSE ├── README.md ├── package.json ├── packages ├── client │ ├── .env.example │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .storybook │ │ ├── default │ │ │ ├── query │ │ │ │ ├── index.ts │ │ │ │ ├── sse.ts │ │ │ │ └── stats.ts │ │ │ └── store │ │ │ │ ├── auth.ts │ │ │ │ ├── index.ts │ │ │ │ └── steamder.ts │ │ ├── main.ts │ │ ├── preview.css │ │ ├── preview.tsx │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── README.md │ ├── barrelsby.json │ ├── index.html │ ├── package.json │ ├── public │ │ ├── _redirects │ │ ├── favicon.png │ │ ├── locales │ │ │ ├── de │ │ │ │ ├── cgu.md │ │ │ │ ├── global │ │ │ │ │ ├── footer.json │ │ │ │ │ ├── information.json │ │ │ │ │ ├── meta.json │ │ │ │ │ ├── navbar.json │ │ │ │ │ └── toast.json │ │ │ │ ├── legal.md │ │ │ │ ├── pages │ │ │ │ │ ├── homepage.json │ │ │ │ │ ├── library.json │ │ │ │ │ ├── login.json │ │ │ │ │ ├── steamder.json │ │ │ │ │ └── steamders.json │ │ │ │ └── translation.json │ │ │ ├── en │ │ │ │ ├── cgu.md │ │ │ │ ├── global │ │ │ │ │ ├── footer.json │ │ │ │ │ ├── information.json │ │ │ │ │ ├── meta.json │ │ │ │ │ ├── navbar.json │ │ │ │ │ └── toast.json │ │ │ │ ├── legal.md │ │ │ │ ├── pages │ │ │ │ │ ├── homepage.json │ │ │ │ │ ├── library.json │ │ │ │ │ ├── login.json │ │ │ │ │ ├── steamder.json │ │ │ │ │ └── steamders.json │ │ │ │ └── translation.json │ │ │ ├── es │ │ │ │ ├── cgu.md │ │ │ │ ├── global │ │ │ │ │ ├── footer.json │ │ │ │ │ ├── information.json │ │ │ │ │ ├── meta.json │ │ │ │ │ ├── navbar.json │ │ │ │ │ └── toast.json │ │ │ │ ├── legal.md │ │ │ │ ├── pages │ │ │ │ │ ├── homepage.json │ │ │ │ │ ├── library.json │ │ │ │ │ ├── login.json │ │ │ │ │ ├── steamder.json │ │ │ │ │ └── steamders.json │ │ │ │ └── translation.json │ │ │ ├── fr │ │ │ │ ├── cgu.md │ │ │ │ ├── global │ │ │ │ │ ├── footer.json │ │ │ │ │ ├── information.json │ │ │ │ │ ├── meta.json │ │ │ │ │ ├── navbar.json │ │ │ │ │ └── toast.json │ │ │ │ ├── legal.md │ │ │ │ ├── pages │ │ │ │ │ ├── homepage.json │ │ │ │ │ ├── library.json │ │ │ │ │ ├── login.json │ │ │ │ │ ├── steamder.json │ │ │ │ │ └── steamders.json │ │ │ │ └── translation.json │ │ │ └── jp │ │ │ │ ├── cgu.md │ │ │ │ ├── global │ │ │ │ ├── footer.json │ │ │ │ ├── information.json │ │ │ │ ├── meta.json │ │ │ │ ├── navbar.json │ │ │ │ └── toast.json │ │ │ │ ├── legal.md │ │ │ │ ├── pages │ │ │ │ ├── homepage.json │ │ │ │ ├── library.json │ │ │ │ ├── login.json │ │ │ │ ├── steamder.json │ │ │ │ └── steamders.json │ │ │ │ └── translation.json │ │ └── styles.css │ ├── src │ │ ├── assets │ │ │ ├── images │ │ │ │ ├── homepage │ │ │ │ │ ├── features.png │ │ │ │ │ ├── logo.png │ │ │ │ │ └── parallax.png │ │ │ │ ├── librarypage │ │ │ │ │ └── cover.png │ │ │ │ ├── loginpage │ │ │ │ │ └── bg.png │ │ │ │ ├── navbar │ │ │ │ │ └── logo.png │ │ │ │ └── steamderpage │ │ │ │ │ └── cover.jpg │ │ │ └── lottie │ │ │ │ └── loader.json │ │ ├── components │ │ │ ├── common │ │ │ │ ├── atoms │ │ │ │ │ ├── Icons │ │ │ │ │ │ ├── Features │ │ │ │ │ │ │ ├── ClockHistory │ │ │ │ │ │ │ │ ├── ClockHistory.stories.tsx │ │ │ │ │ │ │ │ ├── ClockHistory.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── Controller │ │ │ │ │ │ │ │ ├── FeaturesControllerIcon.stories.tsx │ │ │ │ │ │ │ │ ├── FeaturesControllerIcon.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── People │ │ │ │ │ │ │ │ ├── People.stories.tsx │ │ │ │ │ │ │ │ ├── People.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── HowTo │ │ │ │ │ │ │ ├── ControllerIcon │ │ │ │ │ │ │ │ ├── HowToControllerIcon.stories.tsx │ │ │ │ │ │ │ │ ├── HowToControllerIcon.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── PeopleIcon │ │ │ │ │ │ │ │ ├── PeopleIcon.stories.tsx │ │ │ │ │ │ │ │ ├── PeopleIcon.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── RocketIcon │ │ │ │ │ │ │ │ ├── RocketIcon.stories.tsx │ │ │ │ │ │ │ │ ├── RocketIcon.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── SteamIcon │ │ │ │ │ │ │ │ ├── SteamIcon.stories.tsx │ │ │ │ │ │ │ │ ├── SteamIcon.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Navbar │ │ │ │ │ │ │ ├── Logout │ │ │ │ │ │ │ │ ├── Logout.stories.tsx │ │ │ │ │ │ │ │ ├── Logout.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── Steam │ │ │ │ │ │ │ │ ├── Steam.stories.tsx │ │ │ │ │ │ │ │ ├── Steam.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Stats │ │ │ │ │ │ │ ├── Controller │ │ │ │ │ │ │ │ ├── StatsController.stories.tsx │ │ │ │ │ │ │ │ ├── StatsController.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── Diagram │ │ │ │ │ │ │ │ ├── Diagram.stories.tsx │ │ │ │ │ │ │ │ ├── Diagram.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── PersonHearts │ │ │ │ │ │ │ │ ├── PersonHearts.stories.tsx │ │ │ │ │ │ │ │ ├── PersonHearts.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── PersonWorkspace │ │ │ │ │ │ │ │ ├── PersonWorkspace.stories.tsx │ │ │ │ │ │ │ │ ├── PersonWorkspace.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Loader │ │ │ │ │ │ ├── LoaderText │ │ │ │ │ │ │ ├── LoaderText.stories.tsx │ │ │ │ │ │ │ ├── LoaderText.styled.ts │ │ │ │ │ │ │ ├── LoaderText.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── LottieLoader │ │ │ │ │ │ │ ├── LottieLoader.stories.tsx │ │ │ │ │ │ │ ├── LottieLoader.styled.ts │ │ │ │ │ │ │ ├── LottieLoader.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Navbar │ │ │ │ │ │ ├── Brand │ │ │ │ │ │ │ ├── Brand.stories.tsx │ │ │ │ │ │ │ ├── Brand.styled.ts │ │ │ │ │ │ │ ├── Brand.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── NavComponent │ │ │ │ │ │ │ ├── NavComponent.styled.ts │ │ │ │ │ │ │ ├── NavComponent.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── NavItem │ │ │ │ │ │ │ ├── NavItem.props.d.ts │ │ │ │ │ │ │ ├── NavItem.stories.tsx │ │ │ │ │ │ │ ├── NavItem.styled.ts │ │ │ │ │ │ │ ├── NavItem.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── ProgressLabel │ │ │ │ │ │ ├── ProgressLabel.d.ts │ │ │ │ │ │ ├── ProgressLabel.stories.tsx │ │ │ │ │ │ ├── ProgressLabel.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── molecules │ │ │ │ │ ├── Loader │ │ │ │ │ │ ├── Loader.stories.tsx │ │ │ │ │ │ ├── Loader.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Navbar │ │ │ │ │ │ ├── AuthButton │ │ │ │ │ │ │ ├── AuthButton.stories.tsx │ │ │ │ │ │ │ ├── AuthButton.styled.ts │ │ │ │ │ │ │ ├── AuthButton.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Brand │ │ │ │ │ │ │ ├── Brand.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ └── organisms │ │ │ │ │ ├── Footer │ │ │ │ │ ├── Footer.stories.tsx │ │ │ │ │ ├── Footer.tsx │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Navbar │ │ │ │ │ ├── Navbar.stories.tsx │ │ │ │ │ ├── Navbar.tsx │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ ├── features │ │ │ │ ├── atoms │ │ │ │ │ ├── Homepage │ │ │ │ │ │ ├── Features │ │ │ │ │ │ │ ├── Feature │ │ │ │ │ │ │ │ ├── Feature.props.d.ts │ │ │ │ │ │ │ │ ├── Feature.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── Image │ │ │ │ │ │ │ │ ├── FeaturesImage.stories.tsx │ │ │ │ │ │ │ │ ├── FeaturesImage.styled.ts │ │ │ │ │ │ │ │ ├── FeaturesImage.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── GameImage │ │ │ │ │ │ │ ├── GameImage.props.d.ts │ │ │ │ │ │ │ ├── GameImage.stories.ts │ │ │ │ │ │ │ ├── GameImage.styled.ts │ │ │ │ │ │ │ ├── GameImage.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── StyledTitle │ │ │ │ │ │ │ ├── StyledTitle.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Trophy │ │ │ │ │ │ │ ├── Trophy.props.d.ts │ │ │ │ │ │ │ ├── Trophy.stories.tsx │ │ │ │ │ │ │ ├── Trophy.styled.ts │ │ │ │ │ │ │ ├── Trophy.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Library │ │ │ │ │ │ ├── GameCover │ │ │ │ │ │ │ ├── GameCover.props.d.ts │ │ │ │ │ │ │ ├── GameCover.stories.tsx │ │ │ │ │ │ │ ├── GameCover.styled.ts │ │ │ │ │ │ │ ├── GameCover.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Question │ │ │ │ │ │ │ ├── Question.props.d.ts │ │ │ │ │ │ │ ├── Question.stories.tsx │ │ │ │ │ │ │ ├── Question.styled.ts │ │ │ │ │ │ │ ├── Question.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── SelectedCount │ │ │ │ │ │ │ ├── SelectedCount.props.d.ts │ │ │ │ │ │ │ ├── SelectedCount.stories.tsx │ │ │ │ │ │ │ ├── SelectedCount.styled.ts │ │ │ │ │ │ │ ├── SelectedCount.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── SkeletonGameCard │ │ │ │ │ │ │ ├── SkeletonGameCard.styled.ts │ │ │ │ │ │ │ ├── SkeletonGameCard.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── SubmitSelectedButton │ │ │ │ │ │ │ ├── SubmitSelectedButton.props.d.ts │ │ │ │ │ │ │ ├── SubmitSelectedButton.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Steamder │ │ │ │ │ │ ├── CopyIcon │ │ │ │ │ │ │ ├── CopyIcon.stories.tsx │ │ │ │ │ │ │ ├── CopyIcon.styled.ts │ │ │ │ │ │ │ ├── CopyIcon.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── DangerIcon │ │ │ │ │ │ │ ├── DangerIcon.styled.ts │ │ │ │ │ │ │ ├── DangerIcon.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Game │ │ │ │ │ │ │ ├── CountDown │ │ │ │ │ │ │ │ ├── CountDown.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── GrayCover │ │ │ │ │ │ │ │ ├── GrayCover.styled.ts │ │ │ │ │ │ │ │ ├── GrayCover.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── LikeButton │ │ │ │ │ │ │ │ ├── LikeButton.stories.tsx │ │ │ │ │ │ │ │ ├── LikeButton.styled.ts │ │ │ │ │ │ │ │ ├── LikeButton.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── LikeIcon │ │ │ │ │ │ │ │ ├── LikeIcon.stories.tsx │ │ │ │ │ │ │ │ ├── LikeIcon.styled.ts │ │ │ │ │ │ │ │ ├── LikeIcon.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── PassButton │ │ │ │ │ │ │ │ ├── PassButton.stories.tsx │ │ │ │ │ │ │ │ ├── PassButton.styled.ts │ │ │ │ │ │ │ │ ├── PassButton.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── RedCover │ │ │ │ │ │ │ │ ├── RedCover.styled.ts │ │ │ │ │ │ │ │ ├── RedCover.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── SadIcon │ │ │ │ │ │ │ │ ├── SadIcon.stories.tsx │ │ │ │ │ │ │ │ ├── SadIcon.styled.ts │ │ │ │ │ │ │ │ ├── SadIcon.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── SwipedGame │ │ │ │ │ │ │ │ ├── SwipedGame.props.d.ts │ │ │ │ │ │ │ │ ├── SwipedGame.stories.tsx │ │ │ │ │ │ │ │ ├── SwipedGame.styled.ts │ │ │ │ │ │ │ │ ├── SwipedGame.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── ImageContainer │ │ │ │ │ │ │ ├── ImageContainer.props.d.ts │ │ │ │ │ │ │ ├── ImageContainer.props.ts │ │ │ │ │ │ │ ├── ImageContainer.styled.ts │ │ │ │ │ │ │ ├── ImageContainer.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── KickPlayerButton │ │ │ │ │ │ │ ├── KickPlayerButton.props.d.ts │ │ │ │ │ │ │ ├── KickPlayerButton.stories.tsx │ │ │ │ │ │ │ ├── KickPlayerButton.styled.ts │ │ │ │ │ │ │ ├── KickPlayerButton.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── LabelTooltip │ │ │ │ │ │ │ ├── LabelTooltip.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── NotMatchingGames │ │ │ │ │ │ │ ├── NotMatchingGames.props.d.ts │ │ │ │ │ │ │ ├── NotMatchingGames.styled.ts │ │ │ │ │ │ │ ├── NotMatchingGames.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── PlayerNotHavingGame │ │ │ │ │ │ │ ├── PlayerNotHavingGame.props.d.ts │ │ │ │ │ │ │ ├── PlayerNotHavingGame.stories.tsx │ │ │ │ │ │ │ ├── PlayerNotHavingGame.styled.ts │ │ │ │ │ │ │ ├── PlayerNotHavingGame.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── ProfilePicture │ │ │ │ │ │ │ ├── ProfilPicture.tsx │ │ │ │ │ │ │ ├── ProfilePicture.stories.tsx │ │ │ │ │ │ │ ├── ProfilePicture.styled.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── RoomAdminIcon │ │ │ │ │ │ │ ├── RoomAdminIcon.stories.tsx │ │ │ │ │ │ │ ├── RoomAdminIcon.styled.ts │ │ │ │ │ │ │ ├── RoomAdminIcon.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── TiltableImage │ │ │ │ │ │ │ ├── TiltableImage.props.d.ts │ │ │ │ │ │ │ ├── TiltableImage.stories.tsx │ │ │ │ │ │ │ ├── TiltableImage.styled.ts │ │ │ │ │ │ │ ├── TiltableImage.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── SteamdersList │ │ │ │ │ │ ├── CannotCreateSteamder │ │ │ │ │ │ │ ├── CannotCreateSteamder.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── FormLabel │ │ │ │ │ │ │ ├── FormLabel.styled.ts │ │ │ │ │ │ │ ├── FormLabel.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── SubmitButton │ │ │ │ │ │ │ ├── SubmitButton.stories.tsx │ │ │ │ │ │ │ ├── SubmitButton.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── molecules │ │ │ │ │ ├── Homepage │ │ │ │ │ │ ├── GameCard │ │ │ │ │ │ │ ├── GameCard.props.d.ts │ │ │ │ │ │ │ ├── GameCard.stories.tsx │ │ │ │ │ │ │ ├── GameCard.styled.ts │ │ │ │ │ │ │ ├── GameCard.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── HeroSection │ │ │ │ │ │ │ ├── HeroSection.stories.tsx │ │ │ │ │ │ │ ├── HeroSection.styled.ts │ │ │ │ │ │ │ ├── HeroSection.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Library │ │ │ │ │ │ ├── EmptyTab │ │ │ │ │ │ │ ├── EmptyTab.props.d.ts │ │ │ │ │ │ │ ├── EmptyTab.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── GameColumn │ │ │ │ │ │ │ ├── GameColumn.props.d.ts │ │ │ │ │ │ │ ├── GameColumn.styled.ts │ │ │ │ │ │ │ ├── GameColumn.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── GameContainer │ │ │ │ │ │ │ ├── GameContainer.props.d.ts │ │ │ │ │ │ │ ├── GameContainer.stories.tsx │ │ │ │ │ │ │ ├── GameContainer.styled.ts │ │ │ │ │ │ │ ├── GameContainer.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── SkeletonGameLoad │ │ │ │ │ │ │ ├── SkeletonGameLoad.stories.tsx │ │ │ │ │ │ │ ├── SkeletonGameLoad.styled.ts │ │ │ │ │ │ │ ├── SkeletonGameLoad.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Steamder │ │ │ │ │ │ ├── GamesInCommon │ │ │ │ │ │ │ ├── GamesInCommon.styled.ts │ │ │ │ │ │ │ ├── GamesInCommon.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Playing │ │ │ │ │ │ │ ├── ActionColumn │ │ │ │ │ │ │ │ ├── ActionColumn.stories.tsx │ │ │ │ │ │ │ │ ├── ActionColumn.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── CoverImageSwipe │ │ │ │ │ │ │ │ ├── CoverImageSwipe.stories.tsx │ │ │ │ │ │ │ │ ├── CoverImageSwipe.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── GameColumnPlay │ │ │ │ │ │ │ │ ├── GameColumnPlay.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── Header │ │ │ │ │ │ │ │ ├── Header.stories.tsx │ │ │ │ │ │ │ │ ├── Header.styled.ts │ │ │ │ │ │ │ │ └── Header.tsx │ │ │ │ │ │ │ ├── HoverLike │ │ │ │ │ │ │ │ ├── HoverLike.stories.tsx │ │ │ │ │ │ │ │ └── HoverLike.tsx │ │ │ │ │ │ │ ├── HoverPass │ │ │ │ │ │ │ │ ├── HoverPass.stories.tsx │ │ │ │ │ │ │ │ └── HoverPass.tsx │ │ │ │ │ │ │ ├── SwipedGamesBox │ │ │ │ │ │ │ │ ├── SwipedGameBox.stories.tsx │ │ │ │ │ │ │ │ ├── SwipedGamesBox.styled.ts │ │ │ │ │ │ │ │ ├── SwipedGamesBox.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Result │ │ │ │ │ │ │ ├── PlayersNotHavingGame │ │ │ │ │ │ │ │ ├── PlayersNotHavingGame.props.d.ts │ │ │ │ │ │ │ │ ├── PlayersNotHavingGame.stories.tsx │ │ │ │ │ │ │ │ ├── PlayersNotHavingGame.styled.ts │ │ │ │ │ │ │ │ └── PlayersNotHavingGame.tsx │ │ │ │ │ │ │ ├── SelectedGame │ │ │ │ │ │ │ │ ├── SelectedGame.stories.tsx │ │ │ │ │ │ │ │ ├── SelectedGame.styled.ts │ │ │ │ │ │ │ │ └── SelectedGame.tsx │ │ │ │ │ │ │ ├── ShopPageButton │ │ │ │ │ │ │ │ ├── ShopPageButton.stories.tsx │ │ │ │ │ │ │ │ ├── ShopPageButton.styled.ts │ │ │ │ │ │ │ │ └── ShopPageButton.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── WaitingList │ │ │ │ │ │ │ ├── Actions │ │ │ │ │ │ │ │ ├── Actions.stories.tsx │ │ │ │ │ │ │ │ ├── Actions.styled.ts │ │ │ │ │ │ │ │ └── Actions.tsx │ │ │ │ │ │ │ ├── AllGamesSwitch │ │ │ │ │ │ │ │ ├── AllGamesSwitch.props.d.ts │ │ │ │ │ │ │ │ ├── AllGamesSwitch.stories.tsx │ │ │ │ │ │ │ │ ├── AllGamesSwitch.styled.ts │ │ │ │ │ │ │ │ ├── AllGamesSwitch.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── ErrorsList.tsx │ │ │ │ │ │ │ ├── Header │ │ │ │ │ │ │ │ ├── Header.stories.tsx │ │ │ │ │ │ │ │ ├── Header.styled.ts │ │ │ │ │ │ │ │ ├── Header.tsx │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── RoomPlayers.tsx │ │ │ │ │ │ │ ├── SteamderInformations │ │ │ │ │ │ │ │ ├── SteamderInformations.stories.tsx │ │ │ │ │ │ │ │ ├── SteamderInformations.styled.ts │ │ │ │ │ │ │ │ └── SteamderInformations.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── SteamdersList │ │ │ │ │ │ ├── CreateSteamderForm │ │ │ │ │ │ │ ├── CreateSteamderForm.stories.tsx │ │ │ │ │ │ │ ├── CreateSteamderForm.styled.ts │ │ │ │ │ │ │ ├── CreateSteamderForm.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── JoinButton │ │ │ │ │ │ │ ├── JoinButton.stories.tsx │ │ │ │ │ │ │ ├── JoinButton.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── LoadingTable │ │ │ │ │ │ │ ├── LoadingTable.stories.tsx │ │ │ │ │ │ │ ├── LoadingTable.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── MySteamderButtons │ │ │ │ │ │ │ ├── MySteamderButtons.stories.tsx │ │ │ │ │ │ │ ├── MySteamderButtons.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── Pagination │ │ │ │ │ │ │ ├── Pagination.props.d.ts │ │ │ │ │ │ │ ├── Pagination.stories.tsx │ │ │ │ │ │ │ ├── Pagination.styled.ts │ │ │ │ │ │ │ ├── Pagination.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── UnjoinableButton │ │ │ │ │ │ │ ├── UnjoinableButton.stories.tsx │ │ │ │ │ │ │ ├── UnjoinableButton.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ └── organisms │ │ │ │ │ ├── Homepage │ │ │ │ │ ├── FeaturesHome │ │ │ │ │ │ ├── FeaturesHome.stories.tsx │ │ │ │ │ │ ├── FeaturesHome.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── HowTo │ │ │ │ │ │ ├── HowTo.stories.tsx │ │ │ │ │ │ ├── HowTo.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── ParallaxBackground │ │ │ │ │ │ ├── ParallaxBackgroundHome.stories.tsx │ │ │ │ │ │ ├── ParallaxBackgroundHome.styled.ts │ │ │ │ │ │ ├── ParallaxBackgroundHome.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Podium │ │ │ │ │ │ ├── Podium.stories.tsx │ │ │ │ │ │ ├── Podium.styled.ts │ │ │ │ │ │ ├── Podium.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── StatsHome │ │ │ │ │ │ ├── StatsHome.stories.tsx │ │ │ │ │ │ ├── StatsHome.styled.ts │ │ │ │ │ │ ├── StatsHome.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Library │ │ │ │ │ ├── Informations │ │ │ │ │ │ ├── Informations.stories.tsx │ │ │ │ │ │ ├── Informations.styled.ts │ │ │ │ │ │ └── Informations.tsx │ │ │ │ │ ├── RightColumnLibrary.tsx │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Login │ │ │ │ │ ├── Informations │ │ │ │ │ │ ├── InformationsLogin.stories.tsx │ │ │ │ │ │ ├── InformationsLogin.styled.ts │ │ │ │ │ │ └── InformationsLogin.tsx │ │ │ │ │ ├── Progress │ │ │ │ │ │ ├── Progress.stories.tsx │ │ │ │ │ │ ├── Progress.styled.ts │ │ │ │ │ │ └── Progress.tsx │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Steamder │ │ │ │ │ ├── GameRow │ │ │ │ │ │ ├── GameRow.stories.tsx │ │ │ │ │ │ ├── GameRow.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Result │ │ │ │ │ │ ├── GameWinRow │ │ │ │ │ │ │ ├── GameWinRow.stories.tsx │ │ │ │ │ │ │ ├── GameWinRow.styled.ts │ │ │ │ │ │ │ ├── GameWinRow.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── HaventTheGame │ │ │ │ │ │ │ ├── HaventTheGame.stories.tsx │ │ │ │ │ │ │ ├── HaventTheGame.styled.ts │ │ │ │ │ │ │ ├── HaventTheGame.tsx │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ │ ├── SteamdersList │ │ │ │ │ ├── LeftColumnSteamders.tsx │ │ │ │ │ ├── RightColumnSteamders.tsx │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ └── layouts │ │ │ │ ├── templates │ │ │ │ ├── CGU_page.tsx │ │ │ │ ├── Home_page.tsx │ │ │ │ ├── Legal_page.tsx │ │ │ │ ├── Library_page.tsx │ │ │ │ ├── Login_page.tsx │ │ │ │ ├── SteamderPlay_page.tsx │ │ │ │ ├── SteamderWait_page.tsx │ │ │ │ ├── SteamderWin_page.tsx │ │ │ │ └── Steamders_page.tsx │ │ │ │ └── wrappers │ │ │ │ ├── AuthWrapper.tsx │ │ │ │ ├── HelmetWrapper.tsx │ │ │ │ ├── QueryClientWrapper.tsx │ │ │ │ └── index.ts │ │ ├── core │ │ │ ├── environment.ts │ │ │ ├── hooks │ │ │ │ ├── index.ts │ │ │ │ ├── useCheckAuth.ts │ │ │ │ ├── useCountSteamders.ts │ │ │ │ ├── useCreateSteamder.ts │ │ │ │ ├── useDeleteUser.ts │ │ │ │ ├── useGetSteamder.ts │ │ │ │ ├── useGetSteamders.ts │ │ │ │ ├── useJoinSteamder.ts │ │ │ │ ├── useKickSteamder.ts │ │ │ │ ├── useLeaveSteamder.ts │ │ │ │ ├── useLibrary.ts │ │ │ │ └── useStatsApi.ts │ │ │ ├── index.ts │ │ │ ├── queryClient.tsx │ │ │ ├── router.ts │ │ │ ├── services │ │ │ │ ├── API │ │ │ │ │ ├── global │ │ │ │ │ │ ├── auth │ │ │ │ │ │ │ ├── checkAuth.ts │ │ │ │ │ │ │ └── logout.ts │ │ │ │ │ │ └── stats │ │ │ │ │ │ │ └── fetchStats.ts │ │ │ │ │ ├── players │ │ │ │ │ │ ├── deleteUser.ts │ │ │ │ │ │ ├── getLibrary.ts │ │ │ │ │ │ └── updateLibrary.ts │ │ │ │ │ └── steamders │ │ │ │ │ │ ├── count.ts │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── get.ts │ │ │ │ │ │ ├── join.ts │ │ │ │ │ │ ├── kick.ts │ │ │ │ │ │ ├── leave.ts │ │ │ │ │ │ └── search.ts │ │ │ │ ├── SSE │ │ │ │ │ └── login.ts │ │ │ │ └── WebSockets │ │ │ │ │ ├── WebsocketManager.ts │ │ │ │ │ ├── actions │ │ │ │ │ ├── endSteamder.ts │ │ │ │ │ ├── gameEnd.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── joinSteamder.ts │ │ │ │ │ ├── kickSteamder.ts │ │ │ │ │ ├── leaveSteamder.ts │ │ │ │ │ ├── retrieveSteamder.ts │ │ │ │ │ ├── startSteamder.ts │ │ │ │ │ ├── switchDisplayGames.ts │ │ │ │ │ └── updateSteamder.ts │ │ │ │ │ └── send │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── kick.ts │ │ │ │ │ ├── leaveSteamder.ts │ │ │ │ │ ├── startSteamder.ts │ │ │ │ │ ├── swipeCard.ts │ │ │ │ │ ├── switchDisplayGames.ts │ │ │ │ │ ├── unswipeCard.ts │ │ │ │ │ └── updateLibrary.ts │ │ │ ├── types │ │ │ │ ├── ISSEData.d.ts │ │ │ │ ├── ISteamder.d.ts │ │ │ │ ├── ISteamderSearch.d.ts │ │ │ │ ├── IUser.d.ts │ │ │ │ ├── StatsApiResponse.d.ts │ │ │ │ ├── TGameLibrary.d.ts │ │ │ │ └── index.d.ts │ │ │ └── utils │ │ │ │ ├── calculateAllGames.ts │ │ │ │ ├── calculateCommonGames.ts │ │ │ │ ├── cookies.ts │ │ │ │ ├── drawToast.ts │ │ │ │ ├── findMismatchedPlayers.ts │ │ │ │ ├── hasNoCommonGames.ts │ │ │ │ ├── index.ts │ │ │ │ └── loadMarkdown.ts │ │ ├── i18n │ │ │ └── i18n.ts │ │ ├── main.tsx │ │ ├── routeTree.gen.ts │ │ ├── routes │ │ │ ├── __root.tsx │ │ │ ├── cgu.lazy.tsx │ │ │ ├── index.tsx │ │ │ ├── legals.lazy.tsx │ │ │ ├── library.tsx │ │ │ ├── login.lazy.tsx │ │ │ ├── steamder │ │ │ │ └── $steamderId.tsx │ │ │ └── steamders.lazy.tsx │ │ ├── store │ │ │ ├── authStore.ts │ │ │ ├── hoverBtnGameStore.ts │ │ │ ├── index.ts │ │ │ ├── libraryStore.ts │ │ │ ├── steamderStore.ts │ │ │ └── websocketStore.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts └── server │ ├── .env.example │ ├── .eslintrc.js │ ├── Dockerfile │ ├── __tests__ │ └── services │ │ ├── global │ │ └── stats.test.ts │ │ ├── library │ │ └── checkGames.test.ts │ │ └── steamder │ │ └── leaveAndUpdate.test.ts │ ├── jest.config.js │ ├── jest.setup.ts │ ├── package.json │ ├── pnpm-lock.yaml │ ├── railway.json │ ├── src │ ├── @types │ │ ├── fastify.d.ts │ │ ├── jsonwebtoken.d.ts │ │ ├── passport-steam.d.ts │ │ └── ws.d.ts │ ├── app.ts │ ├── auth │ │ └── mw.ts │ ├── config │ │ └── drizzle.config.ts │ ├── domain │ │ ├── entities │ │ │ ├── DeletedUser.ts │ │ │ ├── Games.ts │ │ │ ├── Libraries.ts │ │ │ ├── Players.ts │ │ │ ├── Steamders.ts │ │ │ ├── SteamdersPlayers.ts │ │ │ └── index.ts │ │ └── services │ │ │ ├── authService.ts │ │ │ ├── globalService.ts │ │ │ ├── libraryService.ts │ │ │ ├── playerService.ts │ │ │ ├── progressService.ts │ │ │ ├── steamderPlayerService.ts │ │ │ └── steamderService.ts │ ├── infrastructure │ │ ├── auth │ │ │ ├── steamStrategy.ts │ │ │ └── validateSteam.ts │ │ ├── data │ │ │ ├── index.ts │ │ │ ├── migrate.ts │ │ │ ├── migrations │ │ │ │ └── meta │ │ │ │ │ ├── 0000_snapshot.json │ │ │ │ │ └── _journal.json │ │ │ └── schemas │ │ │ │ ├── deletedUsers.ts │ │ │ │ ├── games.ts │ │ │ │ ├── index.ts │ │ │ │ ├── libraries.ts │ │ │ │ ├── players.ts │ │ │ │ ├── relations.ts │ │ │ │ ├── steamders.ts │ │ │ │ └── steamdersPlayers.ts │ │ ├── repositories │ │ │ ├── DeletedUserRepository.ts │ │ │ ├── GameRepository.ts │ │ │ ├── LibraryRepository.ts │ │ │ ├── PlayerRepository.ts │ │ │ ├── SteamderPlayerRepository.ts │ │ │ ├── SteamderRepository.ts │ │ │ └── index.ts │ │ └── web │ │ │ ├── controllers │ │ │ ├── auth │ │ │ │ ├── index.ts │ │ │ │ ├── logout.ts │ │ │ │ ├── me.ts │ │ │ │ ├── steam.ts │ │ │ │ └── steamCallback.ts │ │ │ ├── debug │ │ │ │ ├── getAllEnv.ts │ │ │ │ ├── index.ts │ │ │ │ ├── seed.ts │ │ │ │ └── truncate.ts │ │ │ ├── global │ │ │ │ ├── index.ts │ │ │ │ └── stats.ts │ │ │ ├── index.ts │ │ │ ├── library │ │ │ │ ├── get.ts │ │ │ │ ├── index.ts │ │ │ │ └── update.ts │ │ │ ├── player │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ └── loginLoad.ts │ │ │ └── steamder │ │ │ │ ├── count.ts │ │ │ │ ├── create.ts │ │ │ │ ├── get.ts │ │ │ │ ├── index.ts │ │ │ │ ├── join.ts │ │ │ │ ├── kick.ts │ │ │ │ ├── leave.ts │ │ │ │ └── paginate.ts │ │ │ ├── options │ │ │ ├── library.option.ts │ │ │ ├── player.option.ts │ │ │ └── steamder.option.ts │ │ │ ├── routes │ │ │ ├── auth.route.ts │ │ │ ├── debug.route.ts │ │ │ ├── global.route.ts │ │ │ ├── index.ts │ │ │ ├── library.route.ts │ │ │ ├── player.route.ts │ │ │ └── steamder.route.ts │ │ │ └── validations │ │ │ ├── index.ts │ │ │ ├── kickValidation.ts │ │ │ ├── steamderValidation.ts │ │ │ └── typeValidation.ts │ ├── plugins │ │ ├── cors.plugin.ts │ │ ├── drizzle.plugin.ts │ │ ├── env.plugin.ts │ │ ├── i18n.plugin.ts │ │ ├── index.ts │ │ ├── logger.plugin.ts │ │ ├── ratelimit.plugin.ts │ │ ├── websocket.plugin.ts │ │ └── ws │ │ │ ├── actions │ │ │ ├── allGamesSwitch.ts │ │ │ ├── index.ts │ │ │ ├── kick.ts │ │ │ ├── leave.ts │ │ │ ├── start.ts │ │ │ ├── swipe.ts │ │ │ ├── unswipe.ts │ │ │ └── update.ts │ │ │ ├── types │ │ │ ├── IPlayerInfo.ts │ │ │ ├── ISteamder.ts │ │ │ └── index.ts │ │ │ └── utils │ │ │ ├── calculateAllGames.ts │ │ │ ├── checkCommonGames.ts │ │ │ ├── checkGameEnd.ts │ │ │ ├── createSteamder.ts │ │ │ ├── deleteSteamder.ts │ │ │ ├── fillPlayerGamesList.ts │ │ │ ├── index.ts │ │ │ ├── joinSteamder.ts │ │ │ ├── startSteamder.ts │ │ │ └── updateCommonGames.ts │ ├── types │ │ ├── fastify.d.ts │ │ ├── jsonwebtoken.d.ts │ │ ├── passport-steam.d.ts │ │ └── ws.d.ts │ └── utils │ │ ├── gamesUtils.ts │ │ └── response.ts │ └── tsconfig.json ├── pnpm-lock.yaml └── pnpm-workspace.yaml /.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps=true -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 -------------------------------------------------------------------------------- /packages/client/.env.example: -------------------------------------------------------------------------------- 1 | VITE_BASE_URL=http://localhost:3000 2 | VITE_BASE_WS_URL=ws://localhost:3000 3 | VITE_SAME_SITE=true 4 | VITE_MODE=development 5 | VITE_STEAMDERS_PER_PAGE=8 -------------------------------------------------------------------------------- /packages/client/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', 'plugin:storybook/recommended'], 5 | ignorePatterns: ['dist', '.eslintrc.cjs'], 6 | parser: '@typescript-eslint/parser', 7 | plugins: ['react-refresh'], 8 | rules: { 9 | 'react-refresh/only-export-components': [ 10 | 'warn', 11 | { allowConstantExport: true }, 12 | ], 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /packages/client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | *storybook.log 27 | -------------------------------------------------------------------------------- /packages/client/.storybook/default/query/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./stats" 2 | export * from "./sse" -------------------------------------------------------------------------------- /packages/client/.storybook/default/query/sse.ts: -------------------------------------------------------------------------------- 1 | export const defaultSSEQuery = [{ 2 | message: "adding_games_to_collection", 3 | type: "info", 4 | complete: false, 5 | count: 0, 6 | progress: 10, 7 | }, { 8 | message: "loading_library_complete", 9 | type: "success", 10 | complete: true, 11 | count: 0, 12 | progress: 100, 13 | }] -------------------------------------------------------------------------------- /packages/client/.storybook/default/query/stats.ts: -------------------------------------------------------------------------------- 1 | export const defaultStatsQuery = { 2 | data: { 3 | matches: 100, 4 | players: 1544, 5 | games: 8741, 6 | steamders: 78, 7 | podium: [ 8 | { 9 | game_id: 570, 10 | score: 75, 11 | }, 12 | { 13 | game_id: 730, 14 | score: 65, 15 | }, 16 | { 17 | game_id: 440, 18 | score: 45, 19 | } 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /packages/client/.storybook/default/store/auth.ts: -------------------------------------------------------------------------------- 1 | export const defaultAuthStore = { 2 | isAuthenticated: true, 3 | toggleAuth: () => {}, 4 | user: { 5 | id: '76561198065059816', 6 | username: 'yedine', 7 | avatar_hash: 'e845df84cbc6129696ec1d96282aa7413597bc18', 8 | steamder: 'ac2e8e2d-3f7c-4c5e-8d6b-1c4b2c3b8c6d' 9 | }, 10 | setUser: () => {} 11 | } -------------------------------------------------------------------------------- /packages/client/.storybook/default/store/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./auth" 2 | export * from "./steamder" -------------------------------------------------------------------------------- /packages/client/.storybook/preview.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); 2 | @import url('https://fonts.googleapis.com/css?family=Abel&display=swap'); 3 | @import url('https://fonts.googleapis.com/css?family=Abhaya+Libre&display=swap'); 4 | @import url('https://fonts.googleapis.com/css?family=Acme&display=swap'); 5 | @import url('https://fonts.googleapis.com/css?family=Actor&display=swap'); 6 | @import url('https://fonts.googleapis.com/css?family=Agdasima&display=swap'); 7 | @import url('https://fonts.googleapis.com/css?family=Archivo+Narrow&display=swap'); 8 | @import url('https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/cyborg/bootstrap.min.css'); -------------------------------------------------------------------------------- /packages/client/.storybook/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": ["../src/**/*.ts", "../src/**/*.tsx", "../src/**/*.stories.tsx"] 4 | } -------------------------------------------------------------------------------- /packages/client/.storybook/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react-swc'; 3 | import tsconfigPaths from 'vite-tsconfig-paths'; 4 | 5 | export default defineConfig({ 6 | plugins: [react(), tsconfigPaths()], 7 | resolve: { 8 | alias: { 9 | '@': '/src', 10 | '@store': '/src/store', 11 | '@features': '/src/components/features', 12 | '@common': '/src/components/common', 13 | '@assets': '/src/assets' 14 | } 15 | } 16 | }); -------------------------------------------------------------------------------- /packages/client/barrelsby.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory": [ 3 | "./src/components/common", 4 | "./src/components/features", 5 | "./src/core/hooks" 6 | ], 7 | "delete": true, 8 | "exclude": [ 9 | "__tests__", 10 | "__stories__", 11 | ".test.", 12 | ".spec." 13 | ], 14 | "include": [ 15 | ".ts", 16 | ".tsx", 17 | ".d.ts" 18 | ], 19 | "location": "all", 20 | "structure": "flat", 21 | "singleQuotes": true, 22 | "noHeader": true, 23 | "exportAll": true 24 | } -------------------------------------------------------------------------------- /packages/client/public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /packages/client/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/public/favicon.png -------------------------------------------------------------------------------- /packages/client/public/locales/de/global/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "cgu": "Allgemeine Geschäftsbedingungen", 3 | "legals": "Impressum", 4 | "bug": "Ein Problem melden", 5 | "copy": "SteamWGP © 2024 - Alle Rechte vorbehalten", 6 | "not_affiliated": "SteamWGP ist nicht mit Valve Corporation oder Steam verbunden.", 7 | "delete": { 8 | "link": "Mein Konto löschen", 9 | "title": "Kontolöschung", 10 | "body": "Sind Sie sicher, dass Sie Ihr Konto löschen möchten? Wenn Sie sich nach der Löschung erneut bei SteamWGP anmelden möchten, <1>müssen Sie 48 Stunden warten, bevor Sie die Plattform wieder nutzen können. Bestätigen Sie diese Aktion?", 11 | "no": "Ich behalte mein Konto", 12 | "confirm": "Ich lösche mein Konto" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/client/public/locales/de/global/information.json: -------------------------------------------------------------------------------- 1 | { 2 | "reset": { 3 | "header": "📢 Wichtige Aktualisierung", 4 | "body": "<3>🚨 Aufgrund der Anfragenlimits von Steam mussten wir alle Spielbibliotheken zurücksetzen, um unsere Datenbank mit Spielen von einer externen Steam-Quelle neu zu füllen.<3><2>Leider müssen Sie daher Ihre Bibliothekseinstellungen erneut aktualisieren, um anzugeben, welche Spiele privat oder öffentlich sind.<3>🙏 Wir entschuldigen uns aufrichtig für die Unannehmlichkeiten und haben Maßnahmen ergriffen, um solche Vorfälle in Zukunft zu verhindern. <1>Mehr über dieses Ereignis erfahren.", 5 | "button": "OK" 6 | } 7 | } -------------------------------------------------------------------------------- /packages/client/public/locales/de/global/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "Startseite", 3 | "library": "Meine Bibliothek", 4 | "my_steamder": "Meine Steamder", 5 | "steamders": "Liste der Steamders", 6 | "donate": "Spenden", 7 | "logout": "Abmelden", 8 | "login": "Anmelden" 9 | } 10 | -------------------------------------------------------------------------------- /packages/client/public/locales/de/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "loading": "Wird geladen ..." 3 | } -------------------------------------------------------------------------------- /packages/client/public/locales/en/global/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "cgu": "Terms of Use", 3 | "legals": "Legal Notice", 4 | "bug": "Report an Issue", 5 | "copy": "SteamWGP © 2024 - All rights reserved", 6 | "not_affiliated": "This site is not affiliated with Valve Corporation", 7 | "delete": { 8 | "link": "Delete my account", 9 | "title": "Account Deletion", 10 | "body": "Are you sure you want to delete your account? If you wish to reconnect to SteamWGP after deleting it, <1>you will need to wait 48 hours before you can use the platform again. Do you confirm this action?", 11 | "no": "I'll keep my account", 12 | "confirm": "I delete my account" 13 | } 14 | } -------------------------------------------------------------------------------- /packages/client/public/locales/en/global/information.json: -------------------------------------------------------------------------------- 1 | { 2 | "reset": { 3 | "header": "📢 Important Update", 4 | "body": "<3>🚨 Due to Steam's request limits, we had to reset all game libraries while refilling our database with games from an external Steam source.<3><2>Unfortunately, this means you will need to update your library settings again to indicate which games are private or public.<3>🙏 We sincerely apologize for this inconvenience and have taken measures to prevent such incidents in the future. <1>Learn more about this incident.", 5 | "button": "OK" 6 | } 7 | } -------------------------------------------------------------------------------- /packages/client/public/locales/en/global/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "Home", 3 | "library": "My library", 4 | "my_steamder": "My Steamder", 5 | "steamders": "Steamders", 6 | "donate": "Donate", 7 | "logout": "Log out", 8 | "login": "Log in" 9 | } -------------------------------------------------------------------------------- /packages/client/public/locales/en/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "loading": "Loading..." 3 | } -------------------------------------------------------------------------------- /packages/client/public/locales/es/global/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "cgu": "Términos y Condiciones", 3 | "legals": "Aviso legal", 4 | "bug": "Reportar un problema", 5 | "copy": "SteamWGP © 2024 - Todos los derechos reservados", 6 | "not_affiliated": "SteamWGP no está afiliado a Valve Corporation", 7 | "delete": { 8 | "link": "Eliminar mi cuenta", 9 | "title": "Eliminación de cuenta", 10 | "body": "¿Estás seguro de que quieres eliminar tu cuenta? Si deseas volver a conectarte a SteamWGP después de eliminarla, <1>deberás esperar 48 horas para poder utilizar la plataforma nuevamente. ¿Confirmas esta acción?", 11 | "no": "Conservo mi cuenta", 12 | "confirm": "Eliminar mi cuenta" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/client/public/locales/es/global/information.json: -------------------------------------------------------------------------------- 1 | { 2 | "reset": { 3 | "header": "📢 Actualización Importante", 4 | "body": "<3>🚨 Debido a los límites de solicitudes de Steam, tuvimos que restablecer todas las bibliotecas de juegos para rellenar nuevamente nuestra base de datos con juegos de una fuente externa a Steam.<3><2>Desafortunadamente, esto significa que necesitarás actualizar nuevamente la configuración de tu biblioteca para indicar cuáles juegos son privados o públicos.<3>🙏 Nos disculpamos sinceramente por los inconvenientes y hemos tomado medidas para evitar que esto suceda en el futuro. <1>Más información sobre este incidente.", 5 | "button": "OK" 6 | } 7 | } -------------------------------------------------------------------------------- /packages/client/public/locales/es/global/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "Inicio", 3 | "library": "Mi biblioteca", 4 | "my_steamder": "Mi Steamder", 5 | "steamders": "Lista de Steamders", 6 | "donate": "Donar", 7 | "logout": "Cerrar sesión", 8 | "login": "Iniciar sesión" 9 | } 10 | -------------------------------------------------------------------------------- /packages/client/public/locales/es/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "loading": "Cargando ..." 3 | } -------------------------------------------------------------------------------- /packages/client/public/locales/fr/global/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "cgu": "Conditions Générales d'Utilisation", 3 | "legals": "Mentions légales", 4 | "bug": "Signaler un problème", 5 | "copy": "SteamWGP © 2024 - Tous droits réservés", 6 | "not_affiliated": "Ce site n'est pas affilié à Valve Corporation", 7 | "delete": { 8 | "link": "Supprimer mon compte", 9 | "title": "Suppression de compte", 10 | "body": "Êtes-vous sûr de vouloir supprimer votre compte ? Si vous souhaitez vous reconnecter à SteamWGP après la suppression de celui-ci, <1>vous devrez attendre 48 heures pour pouvoir re-utiliser la plateforme. Confirmez-vous cette action?", 11 | "no": "Je garde mon compte", 12 | "confirm": "Je supprime mon compte" 13 | } 14 | } -------------------------------------------------------------------------------- /packages/client/public/locales/fr/global/information.json: -------------------------------------------------------------------------------- 1 | { 2 | "reset": { 3 | "header": "📢 Mise à jour importante", 4 | "body": "<3>🚨 En raison des limites de requêtes imposées par Steam, nous avons dû réinitialiser toutes les bibliothèques de jeux au moment de re-remplir la base de données de tout les jeux en prenant une ressource hors-Steam.<3><2>Vous devrez donc, malheureusement, mettre à jour les paramètres de votre bibliothèque pour indiquer quels jeux sont privés ou publics à nouveau.<3>🙏 Nous vous prions de nous excuser sincèrement pour ce désagrément et avons pris des mesures pour éviter que cela se reproduise à l'avenir. <1>En savoir plus sur cet incident.", 5 | "button": "OK" 6 | } 7 | } -------------------------------------------------------------------------------- /packages/client/public/locales/fr/global/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "Accueil", 3 | "library": "Ma bibliothèque", 4 | "my_steamder": "Ma Steamder", 5 | "steamders": "Liste des Steamders", 6 | "donate": "Faire un don", 7 | "logout": "Déconnexion", 8 | "login": "Connexion" 9 | } -------------------------------------------------------------------------------- /packages/client/public/locales/fr/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "loading": "Chargement en cours ..." 3 | } -------------------------------------------------------------------------------- /packages/client/public/locales/jp/global/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "cgu": "利用規約", 3 | "legals": "法的表記", 4 | "bug": "問題を報告する", 5 | "copy": "SteamWGP © 2024 - 全著作権所有", 6 | "not_affiliated": "SteamWGPはValve Corporationとは関係ありません。", 7 | "delete": { 8 | "link": "アカウントを削除する", 9 | "title": "アカウントの削除", 10 | "body": "アカウントを削除してもよろしいですか?削除後にSteamWGPに再接続する場合、<1>プラットフォームを再利用する前に48時間待つ必要があります。このアクションを確認しますか?", 11 | "no": "アカウントを保持する", 12 | "confirm": "アカウントを削除する" 13 | } 14 | } -------------------------------------------------------------------------------- /packages/client/public/locales/jp/global/information.json: -------------------------------------------------------------------------------- 1 | { 2 | "reset": { 3 | "header": "📢 重要な更新", 4 | "body": "<3>🚨 Steamのリクエスト制限により、Steam外のソースからゲームデータベースを再充填するため、すべてのゲームライブラリをリセットする必要がありました。<3><2>残念ながら、どのゲームがプライベートまたはパブリックかを再設定する必要があります。<3>🙏 この不便を心からお詫び申し上げるとともに、将来的にこのような事態を防ぐための措置を講じました。<1>この出来事についてもっと知る。", 5 | "button": "OK" 6 | } 7 | } -------------------------------------------------------------------------------- /packages/client/public/locales/jp/global/navbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "ホーム", 3 | "library": "マイライブラリ", 4 | "my_steamder": "マイSteamder", 5 | "steamders": "Steamderのリスト", 6 | "donate": "寄付する", 7 | "logout": "ログアウト", 8 | "login": "ログイン" 9 | } -------------------------------------------------------------------------------- /packages/client/public/locales/jp/global/toast.json: -------------------------------------------------------------------------------- 1 | { 2 | "admin_closed_room": "管理者がSteamderを閉じました", 3 | "you_have_been_kicked": "Steamderから追放されました", 4 | "player_has_been_kicked": "プレイヤーがSteamderから追放されました", 5 | "room_begins": "Steamderが始まります", 6 | "updated_library": "ライブラリが更新されました", 7 | "link_copied": "Steamderのリンクがクリップボードにコピーされました", 8 | "logged_in_to_access_library": "ライブラリにアクセスするにはログインしてください", 9 | "invalid_id": "無効なIDです", 10 | "steamder_not_found": "Steamderが見つかりません", 11 | "already_in_steamder": "すでにSteamderに参加しています", 12 | "cannot_join_steamder": "Steamderに参加できません", 13 | "account_deleted": "アカウントが削除されました...またのお越しをお待ちしています!", 14 | "user_in_steamder_cannot_kick": "Steamderに参加中はアカウントを削除できません" 15 | } -------------------------------------------------------------------------------- /packages/client/public/locales/jp/translation.json: -------------------------------------------------------------------------------- 1 | { 2 | "loading": "ロード中" 3 | } -------------------------------------------------------------------------------- /packages/client/public/styles.css: -------------------------------------------------------------------------------- 1 | .nav-pills .nav-link.active, .nav-tabs .nav-link.active { 2 | background: var(--bs-cyan); 3 | user-select: none; 4 | } 5 | 6 | .nav-item { 7 | margin-right: 30px; 8 | } 9 | 10 | .pagination { 11 | --bs-pagination-active-border-color: #d6722a; 12 | --bs-pagination-active-bg: #d6722a; 13 | --bs-pagination-hover-bg: #d6682a; 14 | --bs-pagination-hover-border-color: transparent; 15 | --bs-pagination-focus-color: var(--bs-warning); 16 | } -------------------------------------------------------------------------------- /packages/client/src/assets/images/homepage/features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/src/assets/images/homepage/features.png -------------------------------------------------------------------------------- /packages/client/src/assets/images/homepage/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/src/assets/images/homepage/logo.png -------------------------------------------------------------------------------- /packages/client/src/assets/images/homepage/parallax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/src/assets/images/homepage/parallax.png -------------------------------------------------------------------------------- /packages/client/src/assets/images/librarypage/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/src/assets/images/librarypage/cover.png -------------------------------------------------------------------------------- /packages/client/src/assets/images/loginpage/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/src/assets/images/loginpage/bg.png -------------------------------------------------------------------------------- /packages/client/src/assets/images/navbar/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/src/assets/images/navbar/logo.png -------------------------------------------------------------------------------- /packages/client/src/assets/images/steamderpage/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/client/src/assets/images/steamderpage/cover.jpg -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/ClockHistory/ClockHistory.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { ClockHistoryIcon } from './ClockHistory'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Features', 7 | component: ClockHistoryIcon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const ClockHistory: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/ClockHistory/ClockHistory.tsx: -------------------------------------------------------------------------------- 1 | import { BsClockHistory } from "react-icons/bs"; 2 | 3 | export const ClockHistoryIcon: React.FC = () => { 4 | return( 5 |
6 | 7 |
8 | ); 9 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/ClockHistory/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClockHistory' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/Controller/FeaturesControllerIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { FeaturesControllerIcon as Icon } from './FeaturesControllerIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Features', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Controller: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/Controller/FeaturesControllerIcon.tsx: -------------------------------------------------------------------------------- 1 | import { BsController } from "react-icons/bs"; 2 | 3 | 4 | export const FeaturesControllerIcon: React.FC = () => { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/Controller/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FeaturesControllerIcon' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/People/People.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { People as Icon } from './People'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Features', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const People: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/People/People.tsx: -------------------------------------------------------------------------------- 1 | import { BsPeople } from "react-icons/bs"; 2 | 3 | export const People: React.FC = () => { 4 | return( 5 |
6 | 7 |
8 | ); 9 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/People/index.ts: -------------------------------------------------------------------------------- 1 | export * from './People' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Features/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ClockHistory/ClockHistory" 2 | export * from "./Controller" 3 | export * from "./People/People" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/ControllerIcon/HowToControllerIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { HowToControllerIcon as Icon } from './HowToControllerIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/HowTo', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Controller: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/ControllerIcon/HowToControllerIcon.tsx: -------------------------------------------------------------------------------- 1 | import { IoGameControllerSharp } from "react-icons/io5"; 2 | 3 | export const HowToControllerIcon: React.FC = () => { 4 | return( 5 |
6 | 7 |
); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/ControllerIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HowToControllerIcon' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/PeopleIcon/PeopleIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { PeopleIcon as Icon } from './PeopleIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/HowTo', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const People: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/PeopleIcon/PeopleIcon.tsx: -------------------------------------------------------------------------------- 1 | import { IoPeopleCircleSharp } from "react-icons/io5"; 2 | 3 | export const PeopleIcon: React.FC = () => { 4 | return( 5 |
6 | 7 |
); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/PeopleIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PeopleIcon' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/RocketIcon/RocketIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { RocketIcon as Icon } from './RocketIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/HowTo', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Rocket: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/RocketIcon/RocketIcon.tsx: -------------------------------------------------------------------------------- 1 | import { BsRocketTakeoffFill } from "react-icons/bs"; 2 | 3 | export const RocketIcon: React.FC = () => { 4 | return( 5 |
6 | 7 |
); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/RocketIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RocketIcon' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/SteamIcon/SteamIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SteamIcon as Icon } from './SteamIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/HowTo', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Steam: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/SteamIcon/SteamIcon.tsx: -------------------------------------------------------------------------------- 1 | import { BsSteam } from "react-icons/bs"; 2 | 3 | export const SteamIcon: React.FC = () => { 4 | return( 5 |
6 | 7 |
); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/SteamIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SteamIcon' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/HowTo/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ControllerIcon" 2 | export * from "./PeopleIcon/PeopleIcon" 3 | export * from "./SteamIcon/SteamIcon" 4 | export * from "./RocketIcon/RocketIcon" 5 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Navbar/Logout/Logout.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { LogoutIcon as Icon } from './Logout'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Navbar', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Logout: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Navbar/Logout/Logout.tsx: -------------------------------------------------------------------------------- 1 | import { FaPowerOff } from "react-icons/fa"; 2 | import styled from "styled-components"; 3 | 4 | export const LogoutIcon = styled(FaPowerOff)` 5 | margin-right: 10px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Navbar/Logout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Logout' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Navbar/Steam/Steam.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SteamIconNavbar as Icon } from './Steam'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Navbar', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Steam: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Navbar/Steam/Steam.tsx: -------------------------------------------------------------------------------- 1 | import { FaSteam } from "react-icons/fa"; 2 | import styled from "styled-components"; 3 | 4 | export const SteamIconNavbar = styled(FaSteam)` 5 | margin-right: 10px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Navbar/Steam/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Steam' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Navbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Logout/Logout" 2 | export * from "./Steam/Steam" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/Controller/StatsController.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { StatsControllerIcon as Icon } from './StatsController'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Stats', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Controller: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/Controller/StatsController.tsx: -------------------------------------------------------------------------------- 1 | import { PiGameController } from "react-icons/pi"; 2 | 3 | export const StatsControllerIcon: React.FC = () => { 4 | return ( 5 |
6 | 7 |
8 | ) 9 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/Controller/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StatsController' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/Diagram/Diagram.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { DiagramIcon } from './Diagram'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Stats', 7 | component: DiagramIcon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Diagram: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/Diagram/Diagram.tsx: -------------------------------------------------------------------------------- 1 | import { BsFillDiagram3Fill } from "react-icons/bs"; 2 | 3 | export const DiagramIcon: React.FC = () => { 4 | return ( 5 |
6 | 7 |
8 | ) 9 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/Diagram/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Diagram' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/PersonHearts/PersonHearts.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { PersonHeartsIcon } from './PersonHearts'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Stats', 7 | component: PersonHeartsIcon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const PersonHearts: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/PersonHearts/PersonHearts.tsx: -------------------------------------------------------------------------------- 1 | import { BsPersonHearts } from "react-icons/bs"; 2 | 3 | export const PersonHeartsIcon: React.FC = () => { 4 | return ( 5 |
6 | 7 |
8 | ) 9 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/PersonHearts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PersonHearts' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/PersonWorkspace/PersonWorkspace.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { PersonWorkspaceIcon } from './PersonWorkspace'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Icons/Stats', 7 | component: PersonWorkspaceIcon, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const PersonWorkspace: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/PersonWorkspace/PersonWorkspace.tsx: -------------------------------------------------------------------------------- 1 | import { BsPersonWorkspace } from "react-icons/bs"; 2 | 3 | export const PersonWorkspaceIcon: React.FC = () => { 4 | return ( 5 |
6 | 7 |
8 | ) 9 | } -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/PersonWorkspace/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PersonWorkspace' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/Stats/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Controller" 2 | export * from "./Diagram/Diagram" 3 | export * from "./PersonHearts/PersonHearts" 4 | export * from "./PersonWorkspace/PersonWorkspace" 5 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Icons/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Stats" 2 | export * from "./Navbar" 3 | 4 | export { FeaturesControllerIcon, ClockHistoryIcon, People } from "./Features"; 5 | export { HowToControllerIcon, SteamIcon, PeopleIcon, RocketIcon } from "./HowTo"; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LoaderText/LoaderText.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { LoaderText } from './LoaderText'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Loader/Paragraph', 7 | component: LoaderText, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Paragraph: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LoaderText/LoaderText.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledLoaderText = styled.p` 4 | font-size: 24px; 5 | font-weight: bold; 6 | margin-top: 80px; 7 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LoaderText/LoaderText.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslation } from "react-i18next"; 2 | import { StyledLoaderText } from "."; 3 | 4 | export const LoaderText: React.FC = () => { 5 | const { t } = useTranslation('translation'); 6 | 7 | return { t('loading') } 8 | } -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LoaderText/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./LoaderText" 2 | export * from "./LoaderText.styled" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LottieLoader/LottieLoader.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { LottieLoader } from './LottieLoader'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Loader/Lottie', 7 | component: LottieLoader, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Lottie: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LottieLoader/LottieLoader.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import Lottie from "lottie-react"; 3 | 4 | export const StyledLottie = styled(Lottie)` 5 | width: 450px; 6 | overflow: hidden; 7 | margin-top: -150px; 8 | margin-bottom: 50px; 9 | margin-left: auto; 10 | margin-right: auto; 11 | display: block; 12 | z-index: 1; 13 | position: relative; 14 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LottieLoader/LottieLoader.tsx: -------------------------------------------------------------------------------- 1 | import LoadingController from '@assets/lottie/loader.json'; 2 | import { StyledLottie } from "."; 3 | 4 | export const LottieLoader: React.FC = () => -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/LottieLoader/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./LottieLoader" 2 | export * from "./LottieLoader.styled" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./LoaderText" 2 | export * from "./LottieLoader" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/Brand/Brand.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { NavBrand } from './Brand'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Navbar', 7 | component: NavBrand, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const NavBrandExample: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/Brand/Brand.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const NavImage = styled.img` 4 | width: 37px; 5 | margin-right: 10px; 6 | `; 7 | 8 | export const NavTitle = styled.span` 9 | font-family: 'Archivo Narrow', sans-serif; 10 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/Brand/Brand.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from '@tanstack/react-router'; 3 | import { NavImage, NavTitle } from './Brand.styled'; 4 | import NavbarLogo from '@assets/images/navbar/logo.png'; 5 | 6 | export const NavBrand: React.FC = () => ( 7 | 8 | e.currentTarget.classList.add('animate__rubberBand')} 14 | onMouseLeave={(e) => e.currentTarget.classList.remove('animate__rubberBand')} 15 | /> 16 | SteamWGP 17 | 18 | ); -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/Brand/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Brand.styled' 2 | export * from './Brand' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/NavComponent/NavComponent.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Nav } from 'react-bootstrap'; 3 | 4 | export const StyledNav = styled(Nav)` 5 | font-family: 'Abel', sans-serif; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/NavComponent/NavComponent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyledNav } from './NavComponent.styled'; 3 | 4 | interface NavProps { 5 | children: React.ReactNode; 6 | } 7 | 8 | export const NavComponent: React.FC = ({ children }) => ( 9 | 10 |
    11 | {children} 12 |
13 |
14 | ); -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/NavComponent/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./NavComponent" 2 | export * from "./NavComponent.styled" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/NavItem/NavItem.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface NavItemProps { 2 | to: string; 3 | children: React.ReactNode; 4 | flashy?: boolean; 5 | } -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/NavItem/NavItem.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { NavItem } from './NavItem'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Atoms/Navbar/NavItem', 7 | component: NavItem, 8 | tags: ['autodocs'], 9 | parameters: { 10 | layout: 'centered', 11 | }, 12 | args: { 13 | children: "Lien de navbar", 14 | flashy: false, 15 | to: '/home' 16 | } 17 | }; 18 | 19 | export default meta; 20 | type Story = StoryObj; 21 | 22 | export const FlashyNavItemExample: Story = { 23 | args: { 24 | flashy: true 25 | } 26 | }; 27 | 28 | export const DefaultNavItemExample: Story = { 29 | args: { 30 | flashy: false 31 | } 32 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/NavItem/NavItem.styled.ts: -------------------------------------------------------------------------------- 1 | import { Link } from "@tanstack/react-router"; 2 | import styled from "styled-components"; 3 | 4 | export const StyledNavItem = styled(Link)` 5 | margin-right: 30px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/NavItem/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./NavItem" 2 | export * from "./NavItem.props.d"; 3 | export * from "./NavItem.styled" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/Navbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Brand/Brand" 2 | export * from "./NavComponent" 3 | export * from "./NavItem" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/ProgressLabel/ProgressLabel.d.ts: -------------------------------------------------------------------------------- 1 | export interface ProgressLabelComponentProps { 2 | type: 'info' | 'danger' | 'success'; 3 | message: string; 4 | last: boolean; 5 | complete: boolean; 6 | count?: number; 7 | } -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/ProgressLabel/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProgressLabel' 2 | export * from "./ProgressLabel.d" -------------------------------------------------------------------------------- /packages/client/src/components/common/atoms/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Icons" 2 | export * from "./Loader" 3 | export * from "./Navbar" 4 | export * from "./ProgressLabel/ProgressLabel" -------------------------------------------------------------------------------- /packages/client/src/components/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './atoms/index' 2 | export * from './molecules/index' 3 | export * from './organisms/index' 4 | -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Loader/Loader.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { Loader as Comp } from './Loader'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Molecules/Loader', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Loader: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Loader/Loader.tsx: -------------------------------------------------------------------------------- 1 | import { Col, Row } from "react-bootstrap"; 2 | 3 | import { LoaderText, LottieLoader } from "@ui/atoms"; 4 | 5 | export const Loader: React.FC = () => { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | ) 14 | } -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Loader' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Navbar/AuthButton/AuthButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { AuthButton } from './AuthButton'; 4 | 5 | const meta: Meta = { 6 | title: 'Common/Molecules/Navbar/AuthButton', 7 | component: AuthButton, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | tags: ['autodocs'], 12 | args: { 13 | isAuthenticated: false 14 | } 15 | }; 16 | 17 | export default meta; 18 | type Story = StoryObj; 19 | 20 | export const AuthButtonDisconnected: Story = { 21 | args: { 22 | isAuthenticated: false 23 | } 24 | }; 25 | 26 | export const AuthButtonLogged: Story = { 27 | args: { 28 | isAuthenticated: true 29 | } 30 | }; -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Navbar/AuthButton/AuthButton.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Button } from 'react-bootstrap'; 3 | 4 | export const StyledAuthButton = styled(Button)` 5 | font-family: 'Abel', sans-serif; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Navbar/AuthButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./AuthButton" 2 | export * from "./AuthButton.styled" -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Navbar/Brand/Brand.tsx: -------------------------------------------------------------------------------- 1 | import { Navbar } from 'react-bootstrap'; 2 | 3 | import { NavBrand } from '@ui/atoms'; 4 | 5 | export const Brand: React.FC = () => { 6 | return ( 7 | 8 | 9 | 10 | ) 11 | } -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Navbar/Brand/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Brand" -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/Navbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./AuthButton" 2 | export * from "./Brand" -------------------------------------------------------------------------------- /packages/client/src/components/common/molecules/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Loader/Loader" 2 | export * from "./Navbar" -------------------------------------------------------------------------------- /packages/client/src/components/common/organisms/Footer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Footer' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/organisms/Navbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Navbar' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/common/organisms/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Footer/Footer" 2 | export * from "./Navbar/Navbar" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/Feature/Feature.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface FeatureProps { 2 | last?: boolean; 3 | children?: React.ReactNode 4 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/Feature/Feature.tsx: -------------------------------------------------------------------------------- 1 | import { FeatureProps } from "."; 2 | 3 | export const FeatureHome: React.FC = ({ last, children }) => { 4 | return( 5 |
6 | { children } 7 |
8 | ) 9 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/Feature/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Feature" 2 | export * from "./Feature.props.d" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/Image/FeaturesImage.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { FeaturesImage as Comp } from './FeaturesImage'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Homepage/Atoms/FeaturesImage', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const FeaturesImage: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/Image/FeaturesImage.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | import { Col as C } from "react-bootstrap"; 4 | 5 | export const Image = styled.img` 6 | z-index: 10; 7 | min-height: 300px !important; 8 | margin-top: -130px; 9 | border-bottom-right-radius: 90px; 10 | border-bottom-left-radius: 90px; 11 | object-fit: cover; 12 | `; 13 | 14 | export const Col = styled(C)` 15 | z-index: 2; 16 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/Image/FeaturesImage.tsx: -------------------------------------------------------------------------------- 1 | import { Col, Image } from "." 2 | import HappyPeople from '@assets/images/homepage/features.png'; 3 | 4 | export const FeaturesImage = () => { 5 | return ( 6 | 7 | Group of person enjoying the view of a controller, teasing the happiness when using SteamWGP 8 | 9 | ) 10 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/Image/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./FeaturesImage" 2 | export * from "./FeaturesImage.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Features/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Feature" 2 | export * from "./Image" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/GameImage/GameImage.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface ImageContainerProps { 2 | game_id: number; 3 | golden?: boolean; 4 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/GameImage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameImage" 2 | export * from "./GameImage.props.d" 3 | export * from "./GameImage.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/StyledTitle/StyledTitle.tsx: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledTitle = styled.h2` 4 | font-family: 'Archivo Narrow', sans-serif; 5 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/StyledTitle/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./StyledTitle" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Trophy/Trophy.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface TrophyProps { 2 | color?: "gold" | "silver" | "#cd7f32"; 3 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Trophy/Trophy.styled.ts: -------------------------------------------------------------------------------- 1 | import styled, { keyframes } from "styled-components"; 2 | 3 | import { FaTrophy } from "react-icons/fa"; 4 | 5 | const pulseAnimation = keyframes` 6 | 0% { transform: scale(1); } 7 | 50% { transform: scale(1.05); } 8 | 100% { transform: scale(1); } 9 | `; 10 | 11 | export const StyledTrophy = styled(FaTrophy)` 12 | position: absolute; 13 | top: -25px; 14 | font-size: 40px; 15 | z-index: 2; 16 | color: ${props => props.color || 'gold'}; 17 | animation: ${pulseAnimation} 2s infinite; 18 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Trophy/Trophy.tsx: -------------------------------------------------------------------------------- 1 | import { StyledTrophy, TrophyProps } from "."; 2 | 3 | export const Trophy: React.FC = ({ color }) => { 4 | return ( 5 | 6 | ); 7 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/Trophy/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Trophy" 2 | export * from "./Trophy.props.d" 3 | export * from "./Trophy.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Homepage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Features" 2 | export * from "./GameImage" 3 | export * from "./StyledTitle" 4 | export * from "./Trophy" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/GameCover/GameCover.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface GameCoverProps { 2 | game_id: string; 3 | hidden: boolean; 4 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/GameCover/GameCover.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { GameCover } from './GameCover'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Library/Atoms/GameCover', 7 | component: GameCover, 8 | tags: ['autodocs'], 9 | parameters: { 10 | layout: 'centered', 11 | }, 12 | args: { 13 | game_id: '2021210', 14 | hidden: false 15 | }, 16 | }; 17 | 18 | export default meta; 19 | type Story = StoryObj; 20 | 21 | export const PublicGame: Story = { 22 | args: { 23 | game_id: "10" 24 | } 25 | }; 26 | 27 | export const PrivateGame: Story = { 28 | args: { 29 | hidden: true, 30 | game_id: '2021210' 31 | }, 32 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/GameCover/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameCover" 2 | export * from "./GameCover.props.d" 3 | export * from "./GameCover.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/Question/Question.props.d.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from "react"; 2 | 3 | export type QuestionProps = { 4 | children: ReactNode; 5 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/Question/Question.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { Question as Comp } from './Question'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Library/Atoms', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | args: { 12 | children: 'Question', 13 | }, 14 | }; 15 | 16 | export default meta; 17 | type Story = StoryObj; 18 | 19 | export const QuestionDocumentationLibrary: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/Question/Question.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { BsFillQuestionOctagonFill } from "react-icons/bs"; 3 | 4 | export const StyledQuestionIcon = styled(BsFillQuestionOctagonFill)` 5 | margin-right: 10px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/Question/Question.tsx: -------------------------------------------------------------------------------- 1 | import { QuestionProps, StyledQuestionIcon } from "./"; 2 | 3 | export const Question: React.FC = ({ children }) => { 4 | return( 5 | <> 6 | 7 | { children } 8 |
9 | 10 | ) 11 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/Question/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Question" 2 | export * from "./Question.styled" 3 | export * from "./Question.props.d" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SelectedCount/SelectedCount.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface SelectedCountProps { 2 | type: 'public' | 'private'; 3 | count: number; 4 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SelectedCount/SelectedCount.styled.ts: -------------------------------------------------------------------------------- 1 | import { BsFillCheckCircleFill } from "react-icons/bs"; 2 | import styled from "styled-components"; 3 | 4 | export const StyledCheckIcon = styled(BsFillCheckCircleFill)` 5 | margin-top: -2px; 6 | margin-right: 5px; 7 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SelectedCount/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SelectedCount" 2 | export * from "./SelectedCount.styled" 3 | export * from "./SelectedCount.props.d" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SkeletonGameCard/SkeletonGameCard.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import Skeleton from 'react-loading-skeleton'; 3 | 4 | export const GoodSizedSkeleton = styled(Skeleton)` 5 | z-index: 1; 6 | line-height: 1.5; 7 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SkeletonGameCard/SkeletonGameCard.tsx: -------------------------------------------------------------------------------- 1 | import { GoodSizedSkeleton } from "."; 2 | 3 | export const SkeletonGameCard: React.FC = () => { 4 | return ; 5 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SkeletonGameCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SkeletonGameCard" 2 | export * from "./SkeletonGameCard.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SubmitSelectedButton/SubmitSelectedButton.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface SubmitSelectedButtonProps { 2 | count: number; 3 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/SubmitSelectedButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SubmitSelectedButton" 2 | export * from "./SubmitSelectedButton.props.d" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Library/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameCover" 2 | export * from "./Question" 3 | export { SelectedCount } from "./SelectedCount" 4 | export { SkeletonGameCard } from "./SkeletonGameCard" 5 | export * from "./SubmitSelectedButton" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/CopyIcon/CopyIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { CopyIcon as Icon } from './CopyIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Atoms/CopyIcon', 7 | component: Icon, 8 | parameters: { 9 | layout: 'centered' 10 | }, 11 | args: { 12 | steamderId: '1234567890' 13 | } 14 | }; 15 | 16 | export default meta; 17 | type Story = StoryObj; 18 | 19 | export const CopyIcon: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/CopyIcon/CopyIcon.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { HiOutlineShare } from "react-icons/hi"; 3 | 4 | export const StyledOutlineShareIcon = styled(HiOutlineShare)` 5 | font-size: 24px; 6 | cursor: pointer; 7 | transition: .5s; 8 | opacity: 0.5; 9 | &:hover { 10 | color: #f0ad4e; 11 | transform: scale(1.2); 12 | opacity: 1; 13 | } 14 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/CopyIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./CopyIcon" 2 | export * from "./CopyIcon.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/DangerIcon/DangerIcon.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { BsExclamationOctagonFill } from "react-icons/bs"; 3 | 4 | export const StyledExclamationIcon = styled(BsExclamationOctagonFill)` 5 | font-size: 26px; 6 | margin-left: 50px; 7 | position: absolute; 8 | margin-top: 13px; 9 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/DangerIcon/DangerIcon.tsx: -------------------------------------------------------------------------------- 1 | import { StyledExclamationIcon } from "."; 2 | 3 | export const DangerIcon: React.FC = () => -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/DangerIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./DangerIcon" 2 | export * from "./DangerIcon.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/CountDown/CountDown.tsx: -------------------------------------------------------------------------------- 1 | import Countdown, { zeroPad } from "react-countdown"; 2 | import { useSteamderStore } from "@store/steamderStore"; 3 | 4 | export const CountDown: React.FC = () => { 5 | const { steamder } = useSteamderStore(); 6 | 7 | return ( 8 | 10 | 11 | { zeroPad(minutes) }:{ zeroPad(seconds) } 12 | 13 | } /> 14 | ) 15 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/CountDown/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./CountDown" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/GrayCover/GrayCover.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const GrayDiv = styled.div` 4 | border-radius: 40px; 5 | z-index: 3; 6 | position: absolute; 7 | height: 475.5px; 8 | background: #393939; 9 | width: 317px; 10 | opacity: .6; 11 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/GrayCover/GrayCover.tsx: -------------------------------------------------------------------------------- 1 | import { GrayDiv } from "./GrayCover.styled" 2 | 3 | export const GrayCover = () => -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/GrayCover/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GrayCover.styled' 2 | export * from './GrayCover' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/LikeButton/LikeButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { LikeButton as Comp } from './LikeButton'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Atoms/Game', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const LikeButton: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/LikeButton/LikeButton.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledParagraphLikeBtn = styled.p` 4 | margin-left: 12px; 5 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/LikeButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LikeButton.styled' 2 | export * from './LikeButton' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/LikeIcon/LikeIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { LikeIcon as Comp } from './LikeIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Atoms/Game', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const LikeIcon: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/LikeIcon/LikeIcon.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | import { BsHeartFill } from "react-icons/bs"; 4 | 5 | export const StyledHeart = styled(BsHeartFill)` 6 | z-index: 4; 7 | position: absolute; 8 | font-size: 124px; 9 | margin: 109px; 10 | margin-top: 169px; 11 | margin-left: 108px; 12 | transform: scale(1); 13 | 14 | @keyframes fadeIn { 15 | 0% { opacity: 0; transform: scale(0.5);} 16 | 100% { opacity: 1; transform: scale(1);} 17 | } 18 | 19 | animation: fadeIn 0.5s ease-in-out; 20 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/LikeIcon/LikeIcon.tsx: -------------------------------------------------------------------------------- 1 | import { StyledHeart } from "./LikeIcon.styled"; 2 | 3 | export const LikeIcon = () => -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/LikeIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LikeIcon.styled' 2 | export * from './LikeIcon' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/PassButton/PassButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { PassButton as Comp } from './PassButton'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Atoms/Game', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const PassButton: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/PassButton/PassButton.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledParagraphPassButton = styled.p` 4 | margin-left: 12px; 5 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/PassButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PassButton.styled' 2 | export * from './PassButton' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/RedCover/RedCover.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const RedDiv = styled.div` 4 | border-radius: 40px; 5 | z-index: 3; 6 | position: absolute; 7 | height: 475.5px; 8 | background: #ff0000; 9 | width: 317px; 10 | opacity: .6; 11 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/RedCover/RedCover.tsx: -------------------------------------------------------------------------------- 1 | import { RedDiv } from "./RedCover.styled" 2 | 3 | export const RedCover = () => -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/RedCover/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RedCover.styled' 2 | export * from './RedCover' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SadIcon/SadIcon.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SadIcon as Comp } from './SadIcon'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Atoms/Game', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const SadIcon: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SadIcon/SadIcon.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | import { IoMdSad } from "react-icons/io"; 4 | 5 | export const StyledSad = styled(IoMdSad)` 6 | z-index: 4; 7 | position: absolute; 8 | font-size: 124px; 9 | margin: 109px; 10 | margin-top: 169px; 11 | margin-left: 108px; 12 | transform: scale(1); 13 | 14 | @keyframes fadeIn { 15 | 0% { opacity: 0; transform: scale(0.5);} 16 | 100% { opacity: 1; transform: scale(1);} 17 | } 18 | 19 | animation: fadeIn 0.5s ease-in-out; 20 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SadIcon/SadIcon.tsx: -------------------------------------------------------------------------------- 1 | import { StyledSad } from "./SadIcon.styled"; 2 | 3 | export const SadIcon = () => -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SadIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SadIcon.styled' 2 | export * from './SadIcon' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SwipedGame/SwipedGame.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface SwipedGameProps { 2 | game_id: number; 3 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SwipedGame/SwipedGame.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SwipedGame as Comp } from './SwipedGame'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Atoms/Game', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | args: { 12 | game_id: 1072420 13 | } 14 | }; 15 | 16 | export default meta; 17 | type Story = StoryObj; 18 | 19 | export const SwipedGame: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SwipedGame/SwipedGame.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledLikedGames = styled.img` 4 | object-fit: cover; 5 | width: 60px; 6 | height: 60px; 7 | margin: 9px; 8 | opacity: 0.60; 9 | filter: grayscale(100%); 10 | transition: .3s; 11 | cursor: pointer; 12 | 13 | &:hover { 14 | opacity: .3; 15 | transform: scale(.9); 16 | } 17 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/SwipedGame/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SwipedGame" 2 | export * from "./SwipedGame.props.d" 3 | export * from "./SwipedGame.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/Game/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GrayCover' 2 | export * from './LikeButton' 3 | export * from './LikeIcon' 4 | export * from './PassButton' 5 | export * from './RedCover' 6 | export * from './SadIcon' 7 | export * from './SwipedGame' 8 | export * from "./CountDown" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/ImageContainer/ImageContainer.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface IImageContainer { 2 | children: React.ReactNode; 3 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/ImageContainer/ImageContainer.props.ts: -------------------------------------------------------------------------------- 1 | export interface IImageContainer { 2 | children: React.ReactNode; 3 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/ImageContainer/ImageContainer.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const ImageContainerSteamder = styled.div` 4 | perspective: 1000px; 5 | display: inline-block; 6 | position: relative; 7 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/ImageContainer/ImageContainer.tsx: -------------------------------------------------------------------------------- 1 | import { ImageContainerSteamder, IImageContainer } from "."; 2 | 3 | export const ImageContainer: React.FC = ({ children }) => { 4 | return ( 5 | 6 | { children } 7 | 8 | ) 9 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/ImageContainer/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ImageContainer" 2 | export * from "./ImageContainer.props.d" 3 | export * from "./ImageContainer.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/KickPlayerButton/KickPlayerButton.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface KickPlayerButtonProps { 2 | playerId: string; 3 | steamderId: string; 4 | username: string; 5 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/KickPlayerButton/KickPlayerButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { KickPlayerButton as Comp } from './KickPlayerButton'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Atoms/KickPlayerButton', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | args: { 12 | playerId: "76561198064768200", 13 | steamderId: "76561198064768200", 14 | username: "yedine" 15 | } 16 | }; 17 | 18 | export default meta; 19 | type Story = StoryObj; 20 | 21 | export const KickPlayerButton: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/KickPlayerButton/KickPlayerButton.styled.ts: -------------------------------------------------------------------------------- 1 | import { BsPersonFillX } from "react-icons/bs"; 2 | import styled from "styled-components"; 3 | 4 | export const StyledKickButton = styled.button` 5 | margin: 144px 108px 108px; 6 | margin-left: 92px; 7 | z-index: 1; 8 | border-radius: 19px; 9 | position: absolute; 10 | `; 11 | 12 | export const StyledKickIcon = styled(BsPersonFillX)` 13 | font-size: 29px; 14 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/KickPlayerButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./KickPlayerButton" 2 | export * from "./KickPlayerButton.props.d" 3 | export * from "./KickPlayerButton.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/LabelTooltip/LabelTooltip.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip } from "react-bootstrap"; 2 | 3 | export const LabelTooltip = (message: string) => 4 | 5 | { message } 6 | ; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/LabelTooltip/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./LabelTooltip" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/NotMatchingGames/NotMatchingGames.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface MatchingGamesProps { 2 | player1: string; 3 | player2: string; 4 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/NotMatchingGames/NotMatchingGames.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const NoMarginText = styled.p` 4 | margin-top: 0px; 5 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/NotMatchingGames/NotMatchingGames.tsx: -------------------------------------------------------------------------------- 1 | import { BsExclamationOctagon } from "react-icons/bs"; 2 | import { Trans, useTranslation } from "react-i18next"; 3 | 4 | import { NoMarginText, MatchingGamesProps } from "."; 5 | 6 | export const NotMatchingGames: React.FC = ({ player1, player2 }) => { 7 | const { t } = useTranslation("pages/steamder", { keyPrefix: "steamder.errors" }); 8 | return ( 9 | 10 | }} /> 11 | 12 | ); 13 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/NotMatchingGames/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./NotMatchingGames" 2 | export * from "./NotMatchingGames.props.d" 3 | export * from "./NotMatchingGames.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/PlayerNotHavingGame/PlayerNotHavingGame.props.d.ts: -------------------------------------------------------------------------------- 1 | import { IPlayer } from "@core/types"; 2 | 3 | export interface PlayerNotHavingGameProps { 4 | player: IPlayer; 5 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/PlayerNotHavingGame/PlayerNotHavingGame.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledPlayerNotHavingGameImage = styled.img` 4 | width: 80px; 5 | border-radius: 17px; 6 | transition: all 0.5s; 7 | opacity: 1; 8 | &:hover { 9 | width: 85px; 10 | opacity: 0.8; 11 | } 12 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/PlayerNotHavingGame/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PlayerNotHavingGame" 2 | export * from "./PlayerNotHavingGame.props.d" 3 | export * from "./PlayerNotHavingGame.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/ProfilePicture/ProfilePicture.styled.ts: -------------------------------------------------------------------------------- 1 | import { Image } from "react-bootstrap"; 2 | import styled from "styled-components"; 3 | 4 | export const StyledProfileImage = styled(Image)<{ $isOtherPlayer: boolean, $disabled: boolean }>` 5 | width: 120px; 6 | box-shadow: 0px 0px 19px 0px var(--bs-warning); 7 | border-radius: 23px; 8 | user-select: none; 9 | transition: all 0.5s; 10 | &:hover { 11 | box-shadow: 0px 0px 19px 0px var(--bs-yellow); 12 | width: 115px; 13 | } 14 | ${props => props.$isOtherPlayer ? `margin-top: 52px;` : ''} 15 | ${props => props.$disabled ? `filter: grayscale(100%); opacity: 0.40;` : ``} 16 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/ProfilePicture/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProfilePicture.styled' 2 | export * from './ProfilPicture' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/RoomAdminIcon/RoomAdminIcon.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { GiCrownedHeart } from "react-icons/gi"; 3 | 4 | export const StyledGiCrownedHeart = styled(GiCrownedHeart)<{$isOtherPlayer: boolean}>` 5 | position: absolute; 6 | color: var(--bs-warning); 7 | font-size: 44px; 8 | ${props => props.$isOtherPlayer ? `margin-top: 45px;margin-left:-10px;` : 'margin: -14px;'} 9 | background: #9933cc9c; 10 | box-shadow: 0px 0px 20px 4px var(--bs-yellow); 11 | transition: all 0.5s; 12 | &:hover { 13 | background: #9933cc; 14 | box-shadow: 0px 0px 20px 4px var(--bs-warning); 15 | font-size: 48px; 16 | } 17 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/RoomAdminIcon/RoomAdminIcon.tsx: -------------------------------------------------------------------------------- 1 | import { StyledGiCrownedHeart } from "./RoomAdminIcon.styled"; 2 | 3 | export const RoomAdminIcon: React.FC<{isOtherPlayer: boolean}> = ({ isOtherPlayer }) => { 4 | return ( 5 | 6 | ) 7 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/RoomAdminIcon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RoomAdminIcon.styled' 2 | export * from './RoomAdminIcon' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/TiltableImage/TiltableImage.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface TiltableImageProps { 2 | gameId: number; 3 | hovered: boolean; 4 | alt: string; 5 | zoomAppears?: boolean; 6 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/TiltableImage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./TiltableImage" 2 | export * from "./TiltableImage.props.d" 3 | export * from "./TiltableImage.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/Steamder/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CopyIcon/index' 2 | export { DangerIcon } from './DangerIcon' 3 | export * from './Game' 4 | export * from './ImageContainer/index' 5 | export { KickPlayerButton } from './KickPlayerButton' 6 | export * from './LabelTooltip/index' 7 | export * from './NotMatchingGames/index' 8 | export * from './PlayerNotHavingGame' 9 | export { ProfilPicture } from './ProfilePicture' 10 | export * from './RoomAdminIcon' 11 | export { TiltableImage } from './TiltableImage' -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/CannotCreateSteamder/CannotCreateSteamder.tsx: -------------------------------------------------------------------------------- 1 | import { BsExclamationTriangleFill } from "react-icons/bs"; 2 | 3 | interface CannotCreateSteamderProps { 4 | children: React.ReactNode; 5 | } 6 | 7 | export const CannotCreateSteamder: React.FC = ({ children }) => { 8 | return ( 9 |

10 | 11 |
12 | { children } 13 |

14 | ) 15 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/CannotCreateSteamder/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CannotCreateSteamder' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/FormLabel/FormLabel.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Form } from "react-bootstrap"; 3 | 4 | export const Label = styled(Form.Label)` 5 | user-select: none; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/FormLabel/FormLabel.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslation } from "react-i18next"; 2 | import { BsController } from "react-icons/bs"; 3 | 4 | import { Label } from "./FormLabel.styled"; 5 | 6 | export const FormLabel: React.FC = () => { 7 | const { t } = useTranslation('pages/steamders', { keyPrefix: 'left_column.form' }); 8 | 9 | return () 10 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/FormLabel/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./FormLabel" 2 | export * from "./FormLabel.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/SubmitButton/SubmitButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SubmitButton as Comp } from './SubmitButton'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/SteamdersList/Atoms', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | args: { 12 | name: "Steamder" 13 | } 14 | }; 15 | 16 | export default meta; 17 | type Story = StoryObj; 18 | 19 | export const SubmitButton: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/SubmitButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SubmitButton" -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/SteamdersList/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CannotCreateSteamder/index' 2 | export * from './FormLabel/index' 3 | export * from './SubmitButton/index' 4 | -------------------------------------------------------------------------------- /packages/client/src/components/features/atoms/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Homepage/index' 2 | export * from './Library/index' 3 | export * from './Steamder/index' 4 | export * from './SteamdersList/index' 5 | -------------------------------------------------------------------------------- /packages/client/src/components/features/index.ts: -------------------------------------------------------------------------------- 1 | export * from './atoms' 2 | export * from './molecules' 3 | export * from './organisms' 4 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Homepage/GameCard/GameCard.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface GameCardProps { 2 | size: 'large' | 'small'; 3 | color: "gold" | "silver" | "#cd7f32" 4 | score: { score: number, game_id: number } | null; 5 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Homepage/GameCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameCard" 2 | export * from "./GameCard.styled" 3 | export * from "./GameCard.props.d" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Homepage/HeroSection/HeroSection.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Section = styled.div` 4 | max-width: 522px; 5 | `; 6 | 7 | export const PinkText = styled.span` 8 | color: rgb(218, 48, 211); 9 | font-weight: bold; 10 | `; 11 | 12 | export const PinkTextWhiteBackground = styled.span` 13 | color: rgb(231, 19, 210); 14 | background-color: rgb(255, 255, 255); 15 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Homepage/HeroSection/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./HeroSection" 2 | export * from "./HeroSection.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Homepage/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameCard" 2 | export * from "./HeroSection" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/EmptyTab/EmptyTab.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface EmptyTabProps { 2 | children: React.ReactNode 3 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/EmptyTab/EmptyTab.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { TbMoodEmptyFilled } from "react-icons/tb" 3 | 4 | import { EmptyTabProps } from "." 5 | 6 | export const EmptyTab: React.FC = ({ children }) => { 7 | return ( 8 | <> 9 | 10 |

{ children }

11 | ) 12 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/EmptyTab/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./EmptyTab" 2 | export * from "./EmptyTab.props.d" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameColumn/GameColumn.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface GameColumnProps { 2 | game: { 3 | game_id: string; 4 | hidden: boolean; 5 | }; 6 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameColumn/GameColumn.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | import { Col } from "react-bootstrap"; 4 | 5 | export const StyledCol = styled(Col)` 6 | margin-bottom: 20px; 7 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameColumn/GameColumn.tsx: -------------------------------------------------------------------------------- 1 | import { GameContainer } from "../GameContainer"; 2 | 3 | import { GameColumnProps, StyledCol } from "."; 4 | 5 | export const GameColumn: React.FC = ({ game }) => { 6 | return ( 7 | 8 | ); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameColumn/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameColumn" 2 | export * from "./GameColumn.props.d"; 3 | export * from "./GameColumn.styled"; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameContainer/GameContainer.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface GameContainerProps { 2 | game_id: string; 3 | hidden: boolean; 4 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameContainer/GameContainer.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { GameContainer as Comp } from './GameContainer'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Library/Molecules/GameContainer', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | args: { 12 | game_id: "1072420", 13 | hidden: false 14 | } 15 | }; 16 | 17 | export default meta; 18 | type Story = StoryObj; 19 | 20 | export const GameContainerPublic: Story = { 21 | args: { 22 | hidden: false 23 | } 24 | }; 25 | 26 | export const GameContainerHidden: Story = { 27 | args: { 28 | hidden: true 29 | } 30 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameContainer/GameContainer.tsx: -------------------------------------------------------------------------------- 1 | import { GameCover } from "@features/atoms/Library/GameCover/GameCover"; 2 | import { useLibraryStore } from "@store/libraryStore"; 3 | 4 | import { GameHomepageContainer, GameContainerProps } from "."; 5 | 6 | export const GameContainer: React.FC = ({ game_id, hidden }) => { 7 | const { selected } = useLibraryStore(); 8 | 9 | return( 10 | 11 | 13 | ) 14 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/GameContainer/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameContainer" 2 | export * from "./GameContainer.props.d" 3 | export * from "./GameContainer.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/SkeletonGameLoad/SkeletonGameLoad.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SkeletonGameLoad as Comp } from './SkeletonGameLoad'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Library/Molecules', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const SkeletonLoad: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/SkeletonGameLoad/SkeletonGameLoad.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Col } from "react-bootstrap"; 3 | 4 | export const StyledColSkeleton = styled(Col)` 5 | margin-bottom: 20px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/SkeletonGameLoad/SkeletonGameLoad.tsx: -------------------------------------------------------------------------------- 1 | import { Container } from "react-bootstrap"; 2 | import { SkeletonGameCard } from "@features/atoms/Library/SkeletonGameCard"; 3 | 4 | import { StyledColSkeleton } from "."; 5 | 6 | export const SkeletonGameLoad: React.FC = () => { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/SkeletonGameLoad/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SkeletonGameLoad" 2 | export * from "./SkeletonGameLoad.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Library/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./EmptyTab" 2 | export * from "./GameColumn" 3 | export * from "./GameContainer" 4 | export * from "./SkeletonGameLoad" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/GamesInCommon/GamesInCommon.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledText = styled.p` 4 | margin-top: 7px; 5 | font-size: 17px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/GamesInCommon/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GamesInCommon" 2 | export * from "./GamesInCommon.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/ActionColumn/ActionColumn.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { ActionColumn as Comp } from './ActionColumn'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/Playing', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const ActionColumn: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/ActionColumn/ActionColumn.tsx: -------------------------------------------------------------------------------- 1 | import { Col } from "react-bootstrap"; 2 | 3 | import { LikeButton, PassButton } from "@features/atoms/Steamder"; 4 | import { SwipedGamesBox } from "@features/molecules/Steamder/Playing/SwipedGamesBox"; 5 | 6 | export const ActionColumn = () => { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ) 14 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/ActionColumn/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ActionColumn" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/CoverImageSwipe/CoverImageSwipe.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { CoverImageSwipe as Comp } from './CoverImageSwipe'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/Playing', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const CoverImage: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/CoverImageSwipe/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./CoverImageSwipe" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/GameColumnPlay/GameColumnPlay.tsx: -------------------------------------------------------------------------------- 1 | import { Col } from "react-bootstrap" 2 | import { CoverImageSwipe } from "../CoverImageSwipe/CoverImageSwipe"; 3 | 4 | export const GameColumnPlay = () => { 5 | return ( 6 | 7 | 8 | 9 | ) 10 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/GameColumnPlay/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameColumnPlay" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/Header/Header.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { Header as Comp } from './Header'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/Playing', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Header: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/Header/Header.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Container } from "react-bootstrap"; 3 | 4 | export const StyledContainer = styled(Container)` 5 | background: #000000cc; 6 | margin-top: 21px; 7 | `; 8 | 9 | export const StyledTitle = styled.h3` 10 | height: 76.5938px; 11 | padding-top: 8px; 12 | font-family: Abel, sans-serif; 13 | margin-bottom: -7px; 14 | `; 15 | 16 | export const StyledCountdownText = styled.p` 17 | margin-top: 18px; 18 | color: #8dd1f1; 19 | padding-bottom: 23px; 20 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/HoverLike/HoverLike.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { HoverLike as Comp } from './HoverLike'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/Playing', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const HoverLike: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/HoverLike/HoverLike.tsx: -------------------------------------------------------------------------------- 1 | import { LikeIcon, RedCover } from "@features/atoms"; 2 | 3 | export const HoverLike = () => { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | ); 10 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/HoverPass/HoverPass.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { HoverPass as Comp } from './HoverPass'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/Playing', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const HoverPass: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/HoverPass/HoverPass.tsx: -------------------------------------------------------------------------------- 1 | import { GrayCover, SadIcon } from "@features/atoms/Steamder" 2 | 3 | export const HoverPass = () => { 4 | return ( 5 | <> 6 | 7 | 8 | 9 | ) 10 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/SwipedGamesBox/SwipedGameBox.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SwipedGamesBox as Comp } from './SwipedGamesBox'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/Playing', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const SwipedGamesBox: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/SwipedGamesBox/SwipedGamesBox.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledBox = styled.div` 4 | overflow-y: scroll; 5 | height: 307px; 6 | margin: 12px; 7 | background: #080808ee; 8 | width: 80%; 9 | border-radius: 19px; 10 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/SwipedGamesBox/SwipedGamesBox.tsx: -------------------------------------------------------------------------------- 1 | import { useSteamderStore } from "@store/steamderStore"; 2 | 3 | import { SwipedGame } from "@features/atoms/Steamder/Game/SwipedGame/SwipedGame"; 4 | import { StyledBox } from "./SwipedGamesBox.styled"; 5 | 6 | export const SwipedGamesBox = () => { 7 | const { steamder } = useSteamderStore(); 8 | 9 | return ( 10 | 11 | { steamder?.swiped_games?.map((gameId) => ( 12 | 13 | )) } 14 | 15 | ) 16 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/SwipedGamesBox/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./SwipedGamesBox" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Playing/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ActionColumn/ActionColumn' 2 | export * from './CoverImageSwipe/CoverImageSwipe' 3 | export * from './GameColumnPlay/GameColumnPlay' 4 | export * from './Header/Header' 5 | export * from './HoverLike/HoverLike' 6 | export * from './HoverPass/HoverPass' 7 | export * from './SwipedGamesBox/index' 8 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Result/PlayersNotHavingGame/PlayersNotHavingGame.props.d.ts: -------------------------------------------------------------------------------- 1 | import { IPlayer } from "@core/types"; 2 | 3 | export interface playersWithoutGameProps { 4 | playersWithoutGame: IPlayer[]; 5 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Result/PlayersNotHavingGame/PlayersNotHavingGame.styled.ts: -------------------------------------------------------------------------------- 1 | import { Row as R } from "react-bootstrap"; 2 | import styled from "styled-components"; 3 | 4 | export const Row = styled(R)` 5 | background: #060606ab; 6 | height: 102px; 7 | padding-top: 10px; 8 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Result/PlayersNotHavingGame/PlayersNotHavingGame.tsx: -------------------------------------------------------------------------------- 1 | import { PlayerNotHavingGame } from "@features/atoms/Steamder/PlayerNotHavingGame/PlayerNotHavingGame"; 2 | 3 | import { Row } from "./PlayersNotHavingGame.styled"; 4 | import type { playersWithoutGameProps } from "./PlayersNotHavingGame.props"; 5 | 6 | export const PlayersNotHavingGame: React.FC = ({ playersWithoutGame }) => { 7 | return ( 8 | 9 | { playersWithoutGame.map(player => ( 10 | 11 | )) } 12 | 13 | ); 14 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Result/SelectedGame/SelectedGame.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SelectedGame as Comp } from './SelectedGame'; 4 | 5 | const meta: Meta = { 6 | title: "Features/Steamder/Molecules/Result", 7 | component: Comp, 8 | parameters: { 9 | layout: "fullwidth" 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const SelectedGame: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Result/ShopPageButton/ShopPageButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { ShopPageButton as Comp } from './ShopPageButton'; 4 | 5 | const meta: Meta = { 6 | title: "Features/Steamder/Molecules/Result", 7 | component: Comp, 8 | parameters: { 9 | layout: "fullwidth" 10 | }, 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const ShopPageButton: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Result/ShopPageButton/ShopPageButton.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Col as C } from "react-bootstrap"; 3 | 4 | export const Col = styled(C)` 5 | margin-top: 17px; 6 | text-align: center; 7 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/Result/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PlayersNotHavingGame/PlayersNotHavingGame' 2 | export * from './ShopPageButton/ShopPageButton' 3 | export * from './SelectedGame/SelectedGame' 4 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/Actions/Actions.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { RoomActions as Comp } from './Actions'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/WaitingList', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Actions: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/Actions/Actions.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Row as R } from "react-bootstrap"; 3 | 4 | export const Row = styled(R)` 5 | height: 91px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/AllGamesSwitch/AllGamesSwitch.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface AllGamesSwitchProps { 2 | active: boolean; 3 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/AllGamesSwitch/AllGamesSwitch.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { AllGamesSwitch as Form } from './AllGamesSwitch'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/WaitingList', 7 | component: Form, 8 | parameters: { 9 | layout: 'fullwidth', 10 | }, 11 | args: { 12 | active: true 13 | } 14 | }; 15 | 16 | export default meta; 17 | type Story = StoryObj; 18 | 19 | export const AllGamesSwitch: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/AllGamesSwitch/AllGamesSwitch.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Form } from "react-bootstrap"; 3 | 4 | export const StyledSwitch = styled(Form.Check)` 5 | font-family: Abel, sans-serif; 6 | margin-bottom: 11px; 7 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/AllGamesSwitch/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./AllGamesSwitch" 2 | export * from "./AllGamesSwitch.styled" 3 | export * from "./AllGamesSwitch.props.d" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/Header/Header.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { Header as Comp } from './Header'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/WaitingList', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Header: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/Header/Header.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Container } from "react-bootstrap"; 3 | 4 | export const StyledContainer = styled(Container)` 5 | background: #000000cc; 6 | margin-top: 21px; 7 | `; 8 | 9 | export const StyledTitle = styled.h3` 10 | height: 76.5938px; 11 | padding-top: 8px; 12 | font-family: Abel, sans-serif; 13 | margin-bottom: -7px; 14 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/Header/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Header" 2 | export * from "./Header.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/SteamderInformations/SteamderInformations.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { SteamderInformations as Comp } from './SteamderInformations'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Molecules/WaitingList', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const SteamderInformations: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/SteamderInformations/SteamderInformations.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Container = styled.div` 4 | background: #000000ca; 5 | `; 6 | 7 | export const NoMarginTopText = styled.p` 8 | margin-top: 0; 9 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/WaitingList/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AllGamesSwitch/AllGamesSwitch' 2 | export * from './ErrorsList' 3 | export { Header as SteamderHeader } from './Header/Header' 4 | export * from './Actions/Actions' 5 | export * from './SteamderInformations/SteamderInformations' 6 | export * from './RoomPlayers' 7 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/Steamder/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Result' 2 | export * from './Playing' 3 | export * from './GamesInCommon' 4 | export * from './WaitingList' 5 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/CreateSteamderForm/CreateSteamderForm.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { CreateSteamderForm as Form } from './CreateSteamderForm'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/SteamdersList/Molecules', 7 | component: Form, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | args: { 12 | color: "gold", 13 | score: { 14 | game_id: 1072420, 15 | score: 0.5 16 | }, 17 | size: "large" 18 | } 19 | }; 20 | 21 | export default meta; 22 | type Story = StoryObj; 23 | 24 | export const CreateSteamderForm: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/CreateSteamderForm/CreateSteamderForm.styled.ts: -------------------------------------------------------------------------------- 1 | import { Form } from "react-bootstrap"; 2 | import styled from "styled-components"; 3 | 4 | export const StyledForm = styled(Form)` 5 | font-family: 'Archivo Narrow', sans-serif; 6 | font-size: 21px; 7 | margin-bottom: 47px; 8 | `; 9 | 10 | export const StyledInput = styled(Form.Control)` 11 | width: 79%; 12 | font-family: Abel, sans-serif; 13 | margin-bottom: 11px; 14 | `; 15 | 16 | export const StyledSwitch = styled(Form.Check)` 17 | font-family: Abel, sans-serif; 18 | margin-bottom: 11px; 19 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/CreateSteamderForm/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CreateSteamderForm' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/JoinButton/JoinButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { JoinButton as Comp } from './JoinButton'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/SteamdersList/Molecules', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | args: { 12 | id: "76561198064768200" 13 | } 14 | }; 15 | 16 | export default meta; 17 | type Story = StoryObj; 18 | 19 | export const JoinButton: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/JoinButton/JoinButton.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "@tanstack/react-router" 2 | import { Button, Col } from "react-bootstrap" 3 | import { useTranslation } from "react-i18next" 4 | import { BsPersonPlus } from "react-icons/bs" 5 | 6 | export const JoinButton: React.FC<{ id: string }> = ({ id }) => { 7 | const { t } = useTranslation('pages/steamders', { keyPrefix: 'right_column.table.buttons' }); 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ) 15 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/JoinButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './JoinButton' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/LoadingTable/LoadingTable.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { LoadingTable as Comp } from './LoadingTable'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/SteamdersList/Molecules', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const LoadingTable: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/LoadingTable/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LoadingTable' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/MySteamderButtons/MySteamderButtons.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { MySteamderButtons as Comp } from './MySteamderButtons'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/SteamdersList/Molecules', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const MySteamderButtons: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/MySteamderButtons/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MySteamderButtons' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/Pagination/Pagination.props.d.ts: -------------------------------------------------------------------------------- 1 | export interface IPaginationProps { 2 | totalItems: number; 3 | itemsPerPage: number; 4 | currentPage: number; 5 | onPageChange: (page: number) => void; 6 | } -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/Pagination/Pagination.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { PaginationSteamders as Comp } from './Pagination'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/SteamdersList/Molecules', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth', 10 | }, 11 | args: { 12 | currentPage: 1, 13 | itemsPerPage: 10, 14 | totalItems: 100, 15 | onPageChange: () => {} 16 | } 17 | }; 18 | 19 | export default meta; 20 | type Story = StoryObj; 21 | 22 | export const Pagination: Story = { 23 | args: { 24 | currentPage: 6 25 | } 26 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/Pagination/Pagination.styled.ts: -------------------------------------------------------------------------------- 1 | import { Pagination } from "react-bootstrap"; 2 | import styled from "styled-components"; 3 | 4 | export const PaginateItem = styled(Pagination.Item)` 5 | --bs-pagination-active-border-color: #d6722a; 6 | --bs-pagination-active-bg: #d6722a; 7 | --bs-pagination-hover-bg: #d6682a; 8 | --bs-pagination-hover-border-color: transparent; 9 | --bs-pagination-focus-color: var(--bs-warning); 10 | ` -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/Pagination/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Pagination' 2 | export * from "./Pagination.props.d"; 3 | export * from "./Pagination.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/UnjoinableButton/UnjoinableButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { UnjoinableButton as Comp } from './UnjoinableButton'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/SteamdersList/Molecules', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const UnjoinableButton: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/UnjoinableButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './UnjoinableButton' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/SteamdersList/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CreateSteamderForm/index' 2 | export * from './JoinButton/index' 3 | export * from './LoadingTable/index' 4 | export * from './MySteamderButtons/index' 5 | export * from './Pagination/index' 6 | export * from './UnjoinableButton/index' 7 | -------------------------------------------------------------------------------- /packages/client/src/components/features/molecules/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Homepage' 2 | export * from './Library' 3 | export * from './Steamder' 4 | export * from './SteamdersList' 5 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/FeaturesHome/FeaturesHome.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { FeaturesHome } from './FeaturesHome'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Homepage/Organisms/Features', 7 | component: FeaturesHome, 8 | parameters: { 9 | layout: 'fullwidth' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Features: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/FeaturesHome/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./FeaturesHome" -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/HowTo/HowTo.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { HowTo } from './HowTo'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Homepage/Organisms/Tutorial', 7 | component: HowTo, 8 | parameters: { 9 | layout: 'fullwidth' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Tutorial: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/HowTo/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./HowTo" -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/ParallaxBackground/ParallaxBackgroundHome.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { ParallaxBackgroundHome as Comp } from './ParallaxBackgroundHome'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Homepage/Organisms', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth', 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const ParallaxBackground: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/ParallaxBackground/ParallaxBackgroundHome.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import ParallaxImage from '@assets/images/homepage/parallax.png'; 3 | 4 | import { Col } from "react-bootstrap"; 5 | 6 | export const ParallaxHero = styled.div` 7 | height: 600px; 8 | background: center / cover; 9 | background-image: url(${ParallaxImage}); 10 | `; 11 | 12 | export const HeroColumn = styled(Col)` 13 | z-index: 2; 14 | background: rgba(6,6,6,0.57); 15 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/ParallaxBackground/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ParallaxBackgroundHome" 2 | export * from "./ParallaxBackgroundHome.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/Podium/Podium.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { Podium as Comp } from './Podium'; 4 | 5 | const meta: Meta = { 6 | title: "Features/Homepage/Organisms", 7 | component: Comp, 8 | parameters: { 9 | layout: "fullwidth" 10 | }, 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Podium: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/Podium/Podium.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledPodium = styled.div` 4 | text-align: center; 5 | margin-top: 30px; 6 | display: flex; 7 | justify-content: center; 8 | align-items: flex-end; 9 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/Podium/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Podium" 2 | export * from "./Podium.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/StatsHome/StatsHome.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { StatsHome } from './StatsHome'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Homepage/Organisms/Stats', 7 | component: StatsHome, 8 | parameters: { 9 | layout: 'fullwidth' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Stats: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/StatsHome/StatsHome.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Container } from "react-bootstrap"; 3 | 4 | export const StyledLogoSeparator = styled.img` 5 | z-index: 0; 6 | position: absolute; 7 | margin-left: 46.5%; 8 | margin-top: -4%; 9 | width: 7%; 10 | `; 11 | 12 | export const StyledContainer = styled(Container)` 13 | font-family: 'Archivo Narrow', sans-serif; 14 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/StatsHome/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./StatsHome" 2 | export * from "./StatsHome.styled" -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Homepage/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FeaturesHome' 2 | export * from './HowTo' 3 | export * from './ParallaxBackground/ParallaxBackgroundHome' 4 | export * from './Podium/Podium' 5 | export * from './StatsHome/StatsHome' 6 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Library/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Informations/Informations' 2 | export * from './RightColumnLibrary' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Login/Informations/InformationsLogin.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { InformationsLogin as Comp } from './InformationsLogin'; 4 | 5 | const meta: Meta = { 6 | title: "Features/Login/Organisms", 7 | component: Comp, 8 | parameters: { 9 | layout: "fullwidth" 10 | }, 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const InformationsLogin: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Login/Informations/InformationsLogin.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Col } from "react-bootstrap"; 3 | 4 | export const ColumnLeft = styled(Col)` 5 | background: #060606d2; 6 | padding: 27px; 7 | border-radius: 20px; 8 | `; 9 | 10 | export const ProfilePicture = styled.img` 11 | width: 181px; 12 | border-radius: 21px; 13 | `; 14 | 15 | export const Hello = styled.p` 16 | font-family: Abel, sans-serif; 17 | margin-top: 8px; 18 | font-size: 20px; 19 | `; 20 | 21 | export const ActorFont = styled.p` 22 | font-family: Actor, sans-serif; 23 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Login/Progress/Progress.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { ProgressLogin as Comp } from './Progress'; 4 | 5 | const meta: Meta = { 6 | title: "Features/Login/Organisms", 7 | component: Comp, 8 | parameters: { 9 | layout: "fullwidth" 10 | }, 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const Progress: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Login/Progress/Progress.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { ProgressBar } from "react-bootstrap"; 3 | 4 | export const RightBlock = styled.div` 5 | background: #060606d2; 6 | padding: 36px; 7 | border-radius: 26px; 8 | `; 9 | 10 | export const Title = styled.h4` 11 | font-family: Agdasima, sans-serif; 12 | `; 13 | 14 | export const Progress = styled(ProgressBar)` 15 | margin-top: 23px; 16 | margin-bottom: 7px; 17 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Login/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Informations/InformationsLogin' 2 | export * from './Progress/Progress' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/GameRow/GameRow.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { GameRow as Comp } from './GameRow'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Organisms', 7 | component: Comp, 8 | parameters: { 9 | layout: 'fullwidth' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const GameRow: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/GameRow/GameRow.tsx: -------------------------------------------------------------------------------- 1 | import { Row } from "react-bootstrap"; 2 | import { GameColumnPlay, ActionColumn } from "@features/molecules/Steamder/Playing"; 3 | 4 | export const GameRow = () => { 5 | return ( 6 | 7 | 8 | 9 | 10 | ) 11 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/GameRow/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GameRow' 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/GameWinRow/GameWinRow.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { GameWinRow as Comp } from './GameWinRow'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Organisms/Result', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered', 10 | zustand: { 11 | steamderStore: { 12 | steamder: { 13 | choosed_game: 320 14 | } 15 | }, 16 | } 17 | } 18 | }; 19 | 20 | export default meta; 21 | type Story = StoryObj; 22 | 23 | export const GameWinRow: Story = { 24 | args: { 25 | printShop: false 26 | } 27 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/GameWinRow/GameWinRow.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Row } from "react-bootstrap"; 3 | 4 | export const StyledRow = styled(Row)` 5 | margin-bottom: 17px; 6 | `; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/GameWinRow/GameWinRow.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ShopPageButton, SelectedGame } from "@features/molecules/Steamder/Result"; 3 | import { StyledRow } from "./GameWinRow.styled"; 4 | 5 | interface GameWinRowProps { 6 | printShop: boolean; 7 | } 8 | 9 | export const GameWinRow: React.FC = ({ printShop }) => { 10 | return ( 11 | 12 | 13 | { printShop && } 14 | 15 | ) 16 | }; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/GameWinRow/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GameWinRow" 2 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/HaventTheGame/HaventTheGame.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react'; 2 | 3 | import { HaventTheGame as Comp } from './HaventTheGame'; 4 | 5 | const meta: Meta = { 6 | title: 'Features/Steamder/Organisms/Result', 7 | component: Comp, 8 | parameters: { 9 | layout: 'centered' 10 | } 11 | }; 12 | 13 | export default meta; 14 | type Story = StoryObj; 15 | 16 | export const HaventTheGame: Story = {}; -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/HaventTheGame/HaventTheGame.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const HaventTheGameTitle = styled.p` 4 | margin-bottom: 0px; 5 | background: var(--bs-body-bg); 6 | height: 58px; 7 | padding-top: 11px; 8 | font-size: 25px; 9 | font-family: Abel, sans-serif; 10 | `; 11 | 12 | export const DoesntHaveTheGame = styled.p` 13 | background: var(--bs-body-bg); 14 | height: 35px; 15 | padding: 5px; 16 | `; 17 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/HaventTheGame/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./HaventTheGame" -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/Result/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GameWinRow/GameWinRow' 2 | export * from './HaventTheGame/HaventTheGame' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/Steamder/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Result' 2 | export * from './GameRow' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/SteamdersList/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LeftColumnSteamders' 2 | export * from './RightColumnSteamders' 3 | -------------------------------------------------------------------------------- /packages/client/src/components/features/organisms/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Homepage' 2 | export * from './Library' 3 | export * from './Login' 4 | export * from './Steamder' 5 | export * from './SteamdersList' 6 | -------------------------------------------------------------------------------- /packages/client/src/components/layouts/templates/CGU_page.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | import { Container } from "react-bootstrap"; 4 | import ReactMarkdown from "react-markdown"; 5 | import { useTranslation } from "react-i18next"; 6 | import { loadMarkdown } from "@core/utils"; 7 | 8 | export const CGUpage = () => { 9 | const [markdown, setMarkdown] = useState(""); 10 | const { i18n } = useTranslation(); 11 | 12 | useEffect(() => { 13 | const load = async () => { 14 | const text = await loadMarkdown(i18n.language, 'cgu'); 15 | setMarkdown(text as string); 16 | } 17 | 18 | load(); 19 | }, [i18n.language]); 20 | 21 | return 22 | 23 | ; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/client/src/components/layouts/templates/Home_page.tsx: -------------------------------------------------------------------------------- 1 | import { FeaturesHome, 2 | HowTo, 3 | ParallaxBackgroundHome, 4 | Podium, 5 | StatsHome 6 | } from "@features/organisms/Homepage" 7 | 8 | export const Homepage = () => { 9 | return ( 10 |
11 | 12 | 13 | 14 | 15 | 16 |
17 |
) 18 | } -------------------------------------------------------------------------------- /packages/client/src/components/layouts/templates/Legal_page.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | import { Container } from "react-bootstrap"; 4 | import ReactMarkdown from "react-markdown"; 5 | import { useTranslation } from "react-i18next"; 6 | import { loadMarkdown } from "@core/utils/loadMarkdown"; 7 | 8 | export const Legalpage = () => { 9 | const [markdown, setMarkdown] = useState(""); 10 | const { i18n } = useTranslation(); 11 | 12 | useEffect(() => { 13 | const load = async () => { 14 | const text = await loadMarkdown(i18n.language, "legal"); 15 | setMarkdown(text as string); 16 | } 17 | 18 | load(); 19 | }, [i18n.language]); 20 | 21 | return 22 | 23 | ; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/client/src/components/layouts/wrappers/QueryClientWrapper.tsx: -------------------------------------------------------------------------------- 1 | import { QueryClientProvider } from "@tanstack/react-query"; 2 | 3 | import { queryClient } from "@core/queryClient"; 4 | 5 | export const QueryClientWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => { 6 | return ( 7 | 8 | { children } 9 | 10 | ) 11 | }; -------------------------------------------------------------------------------- /packages/client/src/components/layouts/wrappers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './QueryClientWrapper'; 2 | export * from './AuthWrapper'; 3 | export * from './HelmetWrapper'; -------------------------------------------------------------------------------- /packages/client/src/core/environment.ts: -------------------------------------------------------------------------------- 1 | const env = import.meta.env; 2 | 3 | export const BASE_URL: string = env.VITE_BASE_URL; 4 | export const ELEMENTS_PER_PAGE: number = env.VITE_STEAMDERS_PER_PAGE; 5 | export const SAME_SITE: boolean = env.VITE_SAME_SITE; 6 | export const MODE: 'development' | 'production' = env.VITE_MODE; 7 | export const BASE_WS_URL: string = env.VITE_BASE_WS_URL; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useCheckAuth' 2 | export * from './useCountSteamders' 3 | export * from './useCreateSteamder' 4 | export * from './useDeleteUser' 5 | export * from './useGetSteamder' 6 | export * from './useGetSteamders' 7 | export * from './useJoinSteamder' 8 | export * from './useKickSteamder' 9 | export * from './useLeaveSteamder' 10 | export * from './useLibrary' 11 | export * from './useStatsApi' 12 | -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useCheckAuth.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query'; 2 | import { checkAuth } from '@core/services/API/global/auth/checkAuth'; 3 | 4 | export const useCheckAuth = () => { 5 | return useQuery({ 6 | queryKey: ['auth', 'user'], 7 | queryFn: checkAuth, 8 | select: (data) => data.data 9 | }); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useCountSteamders.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from "@tanstack/react-query"; 2 | import { countSteamders } from "@core/services/API/steamders/count"; 3 | 4 | export const useCountSteamders = () => { 5 | return useQuery({ 6 | queryKey: ["steamders", "count"], 7 | queryFn: countSteamders, 8 | select: (data) => data.data.count[0].count 9 | }); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useCreateSteamder.ts: -------------------------------------------------------------------------------- 1 | import { useMutation, useQueryClient } from "@tanstack/react-query"; 2 | import { createSteamder } from "@core/services/API/steamders/create"; 3 | 4 | export const useCreateSteamder = () => { 5 | const queryClient = useQueryClient(); 6 | 7 | return useMutation({ mutationFn: createSteamder, mutationKey: ['create', 'steamder'], onSuccess: () => { 8 | queryClient.invalidateQueries({ queryKey: ["steamders"] }) 9 | queryClient.invalidateQueries({ queryKey: ["steamders", "count"] }) 10 | }, onError: (err) => { 11 | console.error(err); 12 | throw new Error('Error creating steamder', { cause: { ...err } }) 13 | } }) 14 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useDeleteUser.ts: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import { deleteUser } from "@core/services/API/players/deleteUser"; 3 | import { logout } from "@core/services/API/global/auth/logout"; 4 | 5 | export const useDeleteUser = () => { 6 | return useMutation({ mutationFn: deleteUser, mutationKey: ['delete', 'user'], onSuccess: () => { 7 | logout(); 8 | } }); 9 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useGetSteamder.ts: -------------------------------------------------------------------------------- 1 | import { useMutation } from '@tanstack/react-query'; 2 | import { getSteamder } from '@core/services/API/steamders/get'; 3 | 4 | export const useGetSteamder = (steamderId: string) => { 5 | return useMutation({ mutationFn: () => getSteamder(steamderId), mutationKey: ['steamder', steamderId], retry: false }); 6 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useJoinSteamder.ts: -------------------------------------------------------------------------------- 1 | import { useMutation } from "@tanstack/react-query"; 2 | import { joinSteamder } from "@core/services/API/steamders/join"; 3 | 4 | export const useJoinSteamder = (steamderId: string) => { 5 | return useMutation({ mutationFn: () => joinSteamder(steamderId), mutationKey: ['steamder', steamderId], retry: false }); 6 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useKickSteamder.ts: -------------------------------------------------------------------------------- 1 | import { useMutation, useQueryClient } from "@tanstack/react-query"; 2 | import { kickSteamder } from "@core/services/API/steamders/kick"; 3 | 4 | export const useKickSteamder = (steamderId: string, playerId: string) => { 5 | const queryClient = useQueryClient(); 6 | 7 | return useMutation({ mutationFn: () => kickSteamder(steamderId, playerId), mutationKey: ['kick', 'steamder'], onSuccess: () => { 8 | queryClient.invalidateQueries({ queryKey: ["steamders"] }) 9 | } }); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useLeaveSteamder.ts: -------------------------------------------------------------------------------- 1 | import { useMutation, useQueryClient } from "@tanstack/react-query"; 2 | import { leaveSteamder } from "@core/services/API/steamders/leave"; 3 | 4 | export const useLeaveSteamder = () => { 5 | const queryClient = useQueryClient(); 6 | 7 | return useMutation({ mutationFn: leaveSteamder, mutationKey: ['leave', 'steamder'], onSuccess: () => { 8 | queryClient.invalidateQueries({ queryKey: ["steamders"] }) 9 | queryClient.invalidateQueries({ queryKey: ["steamders", "count"] }) 10 | } }); 11 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useLibrary.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query'; 2 | import { getLibrary } from '@core/services/API/players/getLibrary'; 3 | 4 | export const useGetLibrary = () => { 5 | return useQuery({ 6 | queryKey: ['library', 'get'], 7 | queryFn: getLibrary, 8 | select: (data) => data.data 9 | }); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/core/hooks/useStatsApi.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query'; 2 | import { fetchStats } from '@core/services/API/global/stats/fetchStats'; 3 | 4 | export const useStats = () => { 5 | return useQuery({ 6 | queryKey: ['stats'], 7 | queryFn: fetchStats, 8 | select: (data) => data.data 9 | }); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./queryClient" 2 | export * from "./router" 3 | export * from "./environment" -------------------------------------------------------------------------------- /packages/client/src/core/queryClient.tsx: -------------------------------------------------------------------------------- 1 | import { QueryClient } from "@tanstack/react-query"; 2 | 3 | export const queryClient = new QueryClient({ 4 | defaultOptions: { 5 | queries: { 6 | refetchOnWindowFocus: false, 7 | staleTime: 1000 * 60 * 5, 8 | retry: false 9 | }, 10 | }, 11 | }) -------------------------------------------------------------------------------- /packages/client/src/core/router.ts: -------------------------------------------------------------------------------- 1 | import { routeTree } from "routeTree.gen"; 2 | import { createRouter } from "@tanstack/react-router"; 3 | 4 | export const router = createRouter({ routeTree }) -------------------------------------------------------------------------------- /packages/client/src/core/services/API/global/auth/logout.ts: -------------------------------------------------------------------------------- 1 | import { BASE_URL } from '@core/environment'; 2 | 3 | export const logout = async () => { 4 | try { 5 | const response = await fetch(`${BASE_URL}/auth/logout`, { 6 | credentials: "include", 7 | method: "GET" 8 | }); 9 | if (!response.ok) 10 | throw new Error("Impossible de déconnecter l'utilisateur authentifié") 11 | localStorage.removeItem('loadingLoginComplete'); 12 | } catch (err) { 13 | console.error(err); 14 | } 15 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/API/global/stats/fetchStats.ts: -------------------------------------------------------------------------------- 1 | import { BASE_URL } from '@core/environment'; 2 | 3 | export const fetchStats = async () => { 4 | const response = await fetch(`${BASE_URL}/stats`); 5 | if (!response.ok) 6 | throw new Error('An error occured while fetching stats.'); 7 | return response.json(); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/API/steamders/count.ts: -------------------------------------------------------------------------------- 1 | import { BASE_URL } from '@core/environment'; 2 | 3 | export const countSteamders = () => { 4 | return fetch(`${BASE_URL}/steamder/count`, { 5 | method: 'GET', 6 | credentials: "include" 7 | }).then(response => { 8 | if (!response.ok) 9 | throw new Error('Erreur lors de la récupération du nombre de steamders'); 10 | return response.json(); 11 | }).catch(err => { 12 | console.error("Erreur lors de la récupération du nombre de steamders :", err); 13 | throw new Error(err as string); 14 | }); 15 | } -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/actions/endSteamder.ts: -------------------------------------------------------------------------------- 1 | import { router, queryClient } from "@core"; 2 | import { useAuthStore, useSteamderStore } from "@store"; 3 | 4 | import { drawToast } from "@core/utils" 5 | 6 | export const endSteamder = () => { 7 | const { setSteamder, steamder } = useSteamderStore.getState(); 8 | const { user, setUser } = useAuthStore.getState(); 9 | 10 | if (!user || !steamder) return; 11 | setSteamder(null); 12 | setUser({ ...user, steamder: null }); 13 | queryClient.invalidateQueries({ queryKey: ["steamders"] }); 14 | // check if the user is in the steamder room page 15 | if (router.matchRoute('/steamder')) 16 | router.navigate({ to: '/', replace: true, resetScroll: true }); 17 | drawToast('admin_closed_room', 'info'); 18 | } -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/actions/gameEnd.ts: -------------------------------------------------------------------------------- 1 | import { useAuthStore, useSteamderStore } from "@store"; 2 | 3 | export const gameEnd = (choosed_game: number) => { 4 | const { setSteamder, steamder } = useSteamderStore.getState(); 5 | const { user, setUser } = useAuthStore.getState(); 6 | 7 | if (!user || !steamder) return; 8 | setUser({ ...user, steamder: null }); 9 | setSteamder({ ...steamder, complete: true, choosed_game }); 10 | } -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/actions/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./endSteamder"; 2 | export * from "./joinSteamder"; 3 | export * from "./leaveSteamder"; 4 | export * from "./kickSteamder"; 5 | export * from "./startSteamder"; 6 | export * from "./updateSteamder"; 7 | export * from "./switchDisplayGames"; 8 | export * from "./retrieveSteamder"; 9 | export * from "./gameEnd"; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/actions/retrieveSteamder.ts: -------------------------------------------------------------------------------- 1 | import { useSteamderStore } from "@store/steamderStore"; 2 | 3 | export const retrieveSteamder = (swipedGames: string[], endTime: number) => { 4 | const { setSteamder, steamder } = useSteamderStore.getState(); 5 | if (!steamder) return; 6 | 7 | const swipped = swipedGames.map(game => parseInt(game)); 8 | setSteamder({ 9 | ...steamder, 10 | common_games: steamder.common_games.filter(game => !swipped.includes(game)), 11 | all_games: steamder.all_games.filter(game => !swipped.includes(game)), 12 | swiped_games: swipped, 13 | endTime 14 | }); 15 | 16 | } -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/actions/startSteamder.ts: -------------------------------------------------------------------------------- 1 | import { Navigate } from "@tanstack/react-router"; 2 | import { drawToast } from "@core/utils/drawToast"; 3 | import { useSteamderStore } from "@store/steamderStore"; 4 | 5 | import { queryClient } from "@core"; 6 | 7 | export const startSteamder = (endTime: number, id?: string) => { 8 | const { setSteamder, steamder } = useSteamderStore.getState(); 9 | if (!steamder) return; 10 | setSteamder({ ...steamder, started: true, endTime }); 11 | 12 | queryClient.invalidateQueries({ queryKey: ["steamders"] }); 13 | if (id) 14 | Navigate({ to: `/steamder/${id}` }); 15 | drawToast('room_begins', "success"); 16 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/actions/switchDisplayGames.ts: -------------------------------------------------------------------------------- 1 | import { queryClient } from "@core"; 2 | import { useSteamderStore } from "@store/steamderStore"; 3 | 4 | export const switchDisplayGames = (display_all_games: boolean) => { 5 | const { setSteamder, steamder } = useSteamderStore.getState(); 6 | if (!steamder) return; 7 | 8 | queryClient.invalidateQueries({ queryKey: ["steamders"] }); 9 | setSteamder({ ...steamder, display_all_games }); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kick' 2 | export * from './leaveSteamder' 3 | export * from './startSteamder' 4 | export * from './swipeCard' 5 | export * from './switchDisplayGames' 6 | export * from './unswipeCard' 7 | export * from './updateLibrary' -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/kick.ts: -------------------------------------------------------------------------------- 1 | import useWebSocketStore from "@store/websocketStore"; 2 | 3 | export const kickFromSteamderWS = (playerId: string) => { 4 | const { sendMessage } = useWebSocketStore.getState(); 5 | const data = JSON.stringify({ action: 'kick', payload: { playerId } }); 6 | 7 | sendMessage(data) 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/leaveSteamder.ts: -------------------------------------------------------------------------------- 1 | import useWebSocketStore from "@store/websocketStore"; 2 | 3 | export const leaveSteamder = () => { 4 | const { sendMessage } = useWebSocketStore.getState(); 5 | const data = JSON.stringify({ action: 'leave' }); 6 | 7 | sendMessage(data) 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/startSteamder.ts: -------------------------------------------------------------------------------- 1 | import useWebSocketStore from "@store/websocketStore"; 2 | 3 | export const startSteamder = () => { 4 | const { sendMessage } = useWebSocketStore.getState(); 5 | const data = JSON.stringify({ action: 'start' }); 6 | 7 | sendMessage(data) 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/swipeCard.ts: -------------------------------------------------------------------------------- 1 | import useWebSocketStore from "@store/websocketStore"; 2 | 3 | export const swipeCard = (gameId: number) => { 4 | const { sendMessage } = useWebSocketStore.getState(); 5 | const data = JSON.stringify({ action: 'swipe', payload: { gameId } }); 6 | 7 | sendMessage(data); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/switchDisplayGames.ts: -------------------------------------------------------------------------------- 1 | import useWebSocketStore from "@store/websocketStore"; 2 | 3 | export const switchDisplayGames = () => { 4 | const { sendMessage } = useWebSocketStore.getState(); 5 | const data = JSON.stringify({ action: 'allGamesSwitch' }); 6 | 7 | sendMessage(data); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/unswipeCard.ts: -------------------------------------------------------------------------------- 1 | import useWebSocketStore from "@store/websocketStore"; 2 | 3 | export const unswipeCard = (gameId: number) => { 4 | const { sendMessage } = useWebSocketStore.getState(); 5 | const data = JSON.stringify({ action: 'unswipe', payload: { gameId } }); 6 | 7 | sendMessage(data); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/services/WebSockets/send/updateLibrary.ts: -------------------------------------------------------------------------------- 1 | import useWebSocketStore from "@store/websocketStore"; 2 | 3 | export const updateLibraryWS = (publicGames: string[]) => { 4 | const { sendMessage } = useWebSocketStore.getState(); 5 | const data = JSON.stringify({ action: 'update', payload: { publicGames } }); 6 | 7 | sendMessage(data); 8 | }; -------------------------------------------------------------------------------- /packages/client/src/core/types/ISSEData.d.ts: -------------------------------------------------------------------------------- 1 | export interface ISSEData { 2 | message: string; 3 | type: "info" | "danger" | "success"; 4 | complete: boolean; 5 | count?: number; 6 | progress: number; 7 | } -------------------------------------------------------------------------------- /packages/client/src/core/types/ISteamder.d.ts: -------------------------------------------------------------------------------- 1 | export interface IPlayer { 2 | player_id: string; 3 | username: string; 4 | avatar_hash: string; 5 | profileurl: string; 6 | games: number[]; 7 | } 8 | 9 | export interface ISteamder { 10 | id: string; 11 | name: string; 12 | 13 | admin_id: string; 14 | all_games: number[]; 15 | common_games: number[]; 16 | swiped_games: number[]; 17 | choosed_game: number | null; 18 | 19 | players: IPlayer[]; 20 | 21 | display_all_games: boolean; 22 | private: boolean; 23 | started: boolean; 24 | complete: boolean; 25 | 26 | endTime?: number; 27 | 28 | created_at: Date; 29 | updated_at: Date; 30 | } -------------------------------------------------------------------------------- /packages/client/src/core/types/ISteamderSearch.d.ts: -------------------------------------------------------------------------------- 1 | export interface ISteamderSearch { 2 | id: string; 3 | name: string; 4 | games: number; 5 | created_at: string; 6 | player_count: number; 7 | } -------------------------------------------------------------------------------- /packages/client/src/core/types/IUser.d.ts: -------------------------------------------------------------------------------- 1 | export interface IUser { 2 | id: string; 3 | username: string; 4 | avatar_hash: string; 5 | steamder: string | null; 6 | } -------------------------------------------------------------------------------- /packages/client/src/core/types/StatsApiResponse.d.ts: -------------------------------------------------------------------------------- 1 | export interface StatsApiResponse { 2 | data: { 3 | players: number; 4 | games: number; 5 | steamders: number; 6 | matches: number; 7 | }; 8 | message: string; 9 | } -------------------------------------------------------------------------------- /packages/client/src/core/types/TGameLibrary.d.ts: -------------------------------------------------------------------------------- 1 | export type TGameLibrary = { 2 | game_id: string; 3 | hidden: boolean; 4 | }; -------------------------------------------------------------------------------- /packages/client/src/core/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export type * from "./ISSEData" 2 | export type * from "./IUser" 3 | export type * from "./ISteamder" 4 | export type * from "./ISteamderSearch" 5 | export type * from "./StatsApiResponse"; 6 | export type * from "./TGameLibrary" -------------------------------------------------------------------------------- /packages/client/src/core/utils/calculateAllGames.ts: -------------------------------------------------------------------------------- 1 | import type { IPlayer } from "@core/types/ISteamder"; 2 | 3 | export const calculateAllGames = (players: IPlayer[]) => { 4 | return players.reduce((acc, current) => { 5 | current.games.forEach((game) => { 6 | if (!acc.includes(game)) 7 | acc.push(game); 8 | }); 9 | return acc; 10 | }, [] as number[]); 11 | }; -------------------------------------------------------------------------------- /packages/client/src/core/utils/cookies.ts: -------------------------------------------------------------------------------- 1 | export const getCookieValue = (name: string): string | undefined => { 2 | const matches = document.cookie.match(new RegExp( 3 | // eslint-disable-next-line no-useless-escape 4 | "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" 5 | )); 6 | return matches ? decodeURIComponent(matches[1]) : undefined; 7 | } 8 | 9 | export const setCookieValue = (name: string, value: string, options: { path: string }): void => { 10 | const updatedCookie = `${name}=${encodeURIComponent(value)}; path=${options.path}`; 11 | document.cookie = updatedCookie; 12 | }; 13 | 14 | export const deleteCookie = (name: string): void => { 15 | setCookieValue(name, '', { path: '/' }); 16 | }; -------------------------------------------------------------------------------- /packages/client/src/core/utils/drawToast.ts: -------------------------------------------------------------------------------- 1 | import i18n from "@i18n/i18n"; 2 | import { toast } from "react-toastify"; 3 | 4 | type ToastMethod = "warn" | "success" | "error" | "info" | "error" | "dark" | "warning"; 5 | 6 | export const drawToast = (messageKey: string, method: ToastMethod) => { 7 | const message = i18n.t(messageKey, { ns: ['global/toast'] }) 8 | toast[method](message, { 9 | position: "bottom-right", 10 | autoClose: 2500, 11 | closeOnClick: true, 12 | theme: "colored", 13 | hideProgressBar: true, 14 | }); 15 | }; -------------------------------------------------------------------------------- /packages/client/src/core/utils/hasNoCommonGames.ts: -------------------------------------------------------------------------------- 1 | import type { IPlayer, ISteamder } from "@core/types/ISteamder"; 2 | 3 | export const hasNoCommonGamesWithAnyone = (steamder: ISteamder, player: IPlayer) => { 4 | return steamder.players.some(otherPlayer => { 5 | if (otherPlayer.player_id === player.player_id) 6 | return false; 7 | 8 | return !player.games.some(game => otherPlayer.games.includes(game)); 9 | }); 10 | }; -------------------------------------------------------------------------------- /packages/client/src/core/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./calculateAllGames"; 2 | export * from "./calculateCommonGames"; 3 | export * from "./drawToast" 4 | export * from "./cookies"; 5 | export * from "./findMismatchedPlayers"; 6 | export * from "./hasNoCommonGames"; 7 | export * from "./loadMarkdown" -------------------------------------------------------------------------------- /packages/client/src/core/utils/loadMarkdown.ts: -------------------------------------------------------------------------------- 1 | const availableLanguages = ["en", "fr", "jp", "es", "de"] 2 | 3 | export const loadMarkdown = async (i18n: string, page: 'legal' | 'cgu') => { 4 | const language = availableLanguages.includes(i18n) ? i18n : "fr"; 5 | const path = `/locales/${language}/${page}.md`; 6 | try { 7 | const response = await fetch(path); 8 | return await response.text(); 9 | } catch (error) { 10 | console.error("Failed to load markdown file", error); 11 | return null; 12 | } 13 | }; -------------------------------------------------------------------------------- /packages/client/src/main.tsx: -------------------------------------------------------------------------------- 1 | import './i18n/i18n.ts' 2 | 3 | import { StrictMode } from 'react' 4 | import ReactDOM from 'react-dom/client' 5 | import { RouterProvider } from '@tanstack/react-router' 6 | 7 | import { router } from '@core' 8 | import { QueryClientWrapper, AuthWrapper } from '@layouts/wrappers' 9 | 10 | import 'aos/dist/aos.css'; 11 | import 'react-loading-skeleton/dist/skeleton.css' 12 | 13 | const rootElement = document.getElementById('root')! 14 | if (!rootElement.innerHTML) { 15 | const root = ReactDOM.createRoot(rootElement) 16 | root.render( 17 | 18 | 19 | 20 | 21 | 22 | 23 | , 24 | ) 25 | } -------------------------------------------------------------------------------- /packages/client/src/routes/cgu.lazy.tsx: -------------------------------------------------------------------------------- 1 | import { createLazyFileRoute } from '@tanstack/react-router' 2 | import { CGUpage } from '@layouts/templates/CGU_page' 3 | import { HelmetWrapper } from '@layouts/wrappers/HelmetWrapper' 4 | 5 | export const Route = createLazyFileRoute("/cgu")({ 6 | component: CGU, 7 | }) 8 | 9 | function CGU() { 10 | return ( 11 | 12 | 13 | 14 | ); 15 | } -------------------------------------------------------------------------------- /packages/client/src/routes/index.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | import { createFileRoute } from '@tanstack/react-router' 4 | import { Homepage } from '@layouts/templates/Home_page'; 5 | 6 | import AOS from 'aos'; 7 | import { HelmetWrapper } from '@layouts/wrappers/HelmetWrapper'; 8 | 9 | export const Route = createFileRoute("/")({ 10 | component: Home, 11 | }) 12 | 13 | function Home() { 14 | useEffect(() => { 15 | AOS.init({ 16 | once: true 17 | }); 18 | AOS.refresh(); 19 | }, []); 20 | return ( 21 | 22 | 23 | 24 | ); 25 | } -------------------------------------------------------------------------------- /packages/client/src/routes/legals.lazy.tsx: -------------------------------------------------------------------------------- 1 | import { createLazyFileRoute } from '@tanstack/react-router' 2 | import { Legalpage } from '@layouts/templates/Legal_page' 3 | import { HelmetWrapper } from '@layouts/wrappers/HelmetWrapper'; 4 | 5 | export const Route = createLazyFileRoute("/legals")({ 6 | component: Legals, 7 | }) 8 | 9 | function Legals() { 10 | return ( 11 | 12 | 13 | 14 | ); 15 | } -------------------------------------------------------------------------------- /packages/client/src/routes/login.lazy.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { createLazyFileRoute } from '@tanstack/react-router' 3 | import { Loginpage } from '@layouts/templates/Login_page'; 4 | 5 | import AOS from 'aos'; 6 | import { HelmetWrapper } from '@layouts/wrappers/HelmetWrapper'; 7 | 8 | export const Route = createLazyFileRoute("/login")({ 9 | component: Login 10 | }) 11 | 12 | function Login() { 13 | useEffect(() => { 14 | AOS.init(); 15 | AOS.refresh(); 16 | }, []); 17 | return ( 18 | 19 | 20 | ) 21 | } -------------------------------------------------------------------------------- /packages/client/src/routes/steamders.lazy.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { createLazyFileRoute } from '@tanstack/react-router' 3 | import { SteamdersPage } from '@layouts/templates/Steamders_page'; 4 | 5 | import AOS from 'aos'; 6 | import { HelmetWrapper } from '@layouts/wrappers/HelmetWrapper'; 7 | 8 | export const Route = createLazyFileRoute("/steamders")({ 9 | component: Steamders 10 | }) 11 | 12 | function Steamders() { 13 | useEffect(() => { 14 | AOS.init({ 15 | once: true, 16 | disableMutationObserver: true 17 | }); 18 | AOS.refresh(); 19 | }, []); 20 | return ( 21 | 22 | 23 | ) 24 | } -------------------------------------------------------------------------------- /packages/client/src/store/authStore.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | import { IUser } from '../core/types/IUser'; 3 | 4 | type AuthStore = { 5 | isAuthenticated: boolean; 6 | toggleAuth: (isAuthenticated: boolean) => void; 7 | user: IUser | null; 8 | setUser: (user: IUser | null) => void; 9 | }; 10 | 11 | export const useAuthStore = create((set) => ({ 12 | isAuthenticated: false, 13 | toggleAuth: (isAuthenticated) => set({ isAuthenticated }), 14 | 15 | user: null, 16 | setUser: (user) => set({ user }) 17 | })); -------------------------------------------------------------------------------- /packages/client/src/store/hoverBtnGameStore.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | 3 | type BtnGameStore = { 4 | hoverLike: boolean; 5 | setHoverLike: (hoverLike: boolean) => void; 6 | 7 | hoverPass: boolean; 8 | setHoverPass: (hoverPass: boolean) => void; 9 | }; 10 | 11 | export const useBtnGameStore = create((set) => ({ 12 | hoverLike: false, 13 | setHoverLike: (hoverLike) => set({ hoverLike }), 14 | 15 | hoverPass: false, 16 | setHoverPass: (hoverPass) => set({ hoverPass }) 17 | })); -------------------------------------------------------------------------------- /packages/client/src/store/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./authStore" 2 | export * from "./steamderStore" 3 | export * from "./websocketStore" 4 | export * from "./libraryStore" 5 | export * from "./hoverBtnGameStore" -------------------------------------------------------------------------------- /packages/client/src/store/libraryStore.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | import { TGameLibrary } from '../core/types/TGameLibrary'; 3 | 4 | type LibraryStore = { 5 | library: TGameLibrary[]; 6 | setLibrary: (games: TGameLibrary[]) => void; 7 | 8 | selected: string[]; 9 | setSelected: (selected: string[]) => void; 10 | }; 11 | 12 | export const useLibraryStore = create((set) => ({ 13 | library: [], 14 | setLibrary: (library) => set({ library }), 15 | 16 | selected: [], 17 | setSelected: (selected) => set({ selected }) 18 | })); -------------------------------------------------------------------------------- /packages/client/src/store/steamderStore.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | import { ISteamder } from '../core/types/ISteamder'; 3 | 4 | type SteamderStore = { 5 | steamder: ISteamder | null; 6 | setSteamder: (games: ISteamder | null) => void; 7 | }; 8 | 9 | export const useSteamderStore = create((set) => ({ 10 | steamder: null, 11 | setSteamder: (steamder) => set({ steamder }), 12 | })); -------------------------------------------------------------------------------- /packages/client/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/client/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true 9 | }, 10 | "include": ["vite.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/client/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import tsconfigPaths from 'vite-tsconfig-paths'; 3 | 4 | import { TanStackRouterVite } from '@tanstack/router-vite-plugin' 5 | import { viteStaticCopy } from 'vite-plugin-static-copy'; 6 | 7 | import react from '@vitejs/plugin-react-swc' 8 | 9 | // https://vitejs.dev/config/ 10 | export default defineConfig({ 11 | plugins: [ 12 | react(), 13 | TanStackRouterVite(), 14 | tsconfigPaths(), 15 | viteStaticCopy({ 16 | targets: [ 17 | { 18 | src: './public/locales', 19 | dest: '' 20 | } 21 | ] 22 | }) 23 | ], 24 | }) 25 | -------------------------------------------------------------------------------- /packages/server/.env.example: -------------------------------------------------------------------------------- 1 | PROTOCOL=http 2 | PORT=8000 3 | HOST=localhost 4 | SERVER_HOST=localhost 5 | ORIGIN=localhost:3000 6 | NODE_ENV=development 7 | STEAM_API_KEY=E499123456xxxxxxxxxxxxx 8 | SECRET_KEY=DoYouEatSaladWithSpoon? 9 | FRONT=localhost:3000 10 | 11 | DOMAIN=localhost 12 | 13 | DATABASE_URL=postgres://di.laouid:test@localhost:5432/steamwgp # used in development mode 14 | 15 | PGHOST=mon-endpoint-super-cool.eu-central-1.aws.yanzi.tech 16 | PGDATABASE=steamwgp 17 | PGUSER=di.laouid 18 | PGPASSWORD=WhatIsThePasswordLolDidYouReallyThinkIWouldPutItHere? 19 | ENDPOINT_ID=mon-endpoint-super-cool 20 | 21 | STEAM_GetOwnedGames=http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001 -------------------------------------------------------------------------------- /packages/server/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['@typescript-eslint'], 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | ], 8 | env: { 9 | node: true, 10 | es2021: true, 11 | }, 12 | parserOptions: { 13 | ecmaVersion: 12, 14 | sourceType: 'module', 15 | }, 16 | rules: { 17 | indent: ['error', 2], 18 | '@typescript-eslint/no-unused-vars': ['error'], 19 | 'no-multiple-empty-lines': ['error', { max: 2 }], 20 | 'no-trailing-spaces': ['error'], 21 | 'no-multi-spaces': ['error'], 22 | 'space-infix-ops': ['error'], 23 | '@typescript-eslint/no-explicit-any': 'off' 24 | } 25 | }; -------------------------------------------------------------------------------- /packages/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18 2 | WORKDIR /app 3 | COPY package.json . 4 | COPY pnpm-lock.yaml . 5 | RUN corepack enable && corepack prepare pnpm@9.15.3 --activate 6 | RUN pnpm install 7 | COPY . . 8 | RUN pnpm run build 9 | RUN pnpm add -D ts-node tsconfig-paths 10 | CMD ["pnpm", "start"] 11 | -------------------------------------------------------------------------------- /packages/server/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: "ts-jest", 3 | testEnvironment: "node", 4 | testMatch: ["**/__tests__/**/*.test.ts"], 5 | setupFiles: ["/jest.setup.ts"] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/server/jest.setup.ts: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv" 2 | 3 | dotenv.config({ path: '.env.test' }); -------------------------------------------------------------------------------- /packages/server/railway.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "server", 5 | "build": "pnpm install && pnpm run build", 6 | "start": "pnpm run start" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /packages/server/src/config/drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import "dotenv/config"; 2 | 3 | import { defineConfig } from "drizzle-kit"; 4 | 5 | export default defineConfig({ 6 | schema: "src/infrastructure/data/schemas/index.ts", 7 | out: "src/infrastructure/data/migrations", 8 | dialect: "postgresql", 9 | 10 | dbCredentials: { 11 | url: process.env.DATABASE_URL || '', 12 | }, 13 | verbose: true, 14 | strict: true 15 | }); 16 | -------------------------------------------------------------------------------- /packages/server/src/domain/entities/DeletedUser.ts: -------------------------------------------------------------------------------- 1 | import { InferSelectModel, InferInsertModel } from 'drizzle-orm'; 2 | import { deletedUsers } from '@schemas'; 3 | 4 | export type DeletedUser = InferSelectModel; 5 | export type DeletedUserInsert = InferInsertModel; -------------------------------------------------------------------------------- /packages/server/src/domain/entities/Games.ts: -------------------------------------------------------------------------------- 1 | import { InferSelectModel, InferInsertModel } from 'drizzle-orm'; 2 | import { games } from '@schemas'; 3 | 4 | export type Game = InferSelectModel; 5 | export type GameInsert = InferInsertModel; -------------------------------------------------------------------------------- /packages/server/src/domain/entities/Libraries.ts: -------------------------------------------------------------------------------- 1 | import { InferInsertModel, InferSelectModel } from "drizzle-orm"; 2 | import { libraries } from '@schemas'; 3 | 4 | export type Library = InferSelectModel; 5 | export type LibraryInsert = InferInsertModel; -------------------------------------------------------------------------------- /packages/server/src/domain/entities/Players.ts: -------------------------------------------------------------------------------- 1 | import { InferInsertModel, InferSelectModel } from "drizzle-orm"; 2 | import { players } from "@schemas"; 3 | 4 | export type Player = InferSelectModel; 5 | export type PlayerInsert = InferInsertModel; -------------------------------------------------------------------------------- /packages/server/src/domain/entities/Steamders.ts: -------------------------------------------------------------------------------- 1 | import { InferInsertModel, InferSelectModel } from "drizzle-orm"; 2 | import { steamders } from "@schemas"; 3 | 4 | export type Steamder = InferSelectModel; 5 | export type SteamderInsert = InferInsertModel; -------------------------------------------------------------------------------- /packages/server/src/domain/entities/SteamdersPlayers.ts: -------------------------------------------------------------------------------- 1 | import { InferInsertModel, InferSelectModel } from "drizzle-orm"; 2 | import { steamdersPlayers } from "@schemas"; 3 | 4 | export type SteamderPlayer = InferSelectModel; 5 | export type SteamderPlayerInsert = InferInsertModel; -------------------------------------------------------------------------------- /packages/server/src/domain/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./DeletedUser"; 2 | export * from "./Players"; 3 | export * from "./Steamders"; 4 | export * from "./SteamdersPlayers"; 5 | export * from "./Games"; 6 | export * from "./Libraries"; -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilaouid/steam-wgp/95826746bc7b2e517798a45716f92fcfce51885d/packages/server/src/infrastructure/data/index.ts -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/migrate.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { Pool } from "pg"; 3 | import { migrate } from "drizzle-orm/node-postgres/migrator"; 4 | import { NodePgDatabase, drizzle } from "drizzle-orm/node-postgres"; 5 | 6 | const { DATABASE_URL } = process.env; 7 | 8 | async function main() { 9 | const pool = new Pool({ 10 | connectionString: DATABASE_URL, 11 | }); 12 | 13 | const db: NodePgDatabase = drizzle(pool); 14 | 15 | console.info("Migrating database..."); 16 | 17 | await migrate(db, { 18 | migrationsFolder: "src/infrastructure/data/migrations" 19 | }); 20 | 21 | console.info("Database migrated successfully!"); 22 | 23 | await pool.end(); 24 | } 25 | 26 | main(); 27 | -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/migrations/meta/_journal.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "7", 3 | "dialect": "postgresql", 4 | "entries": [ 5 | { 6 | "idx": 0, 7 | "version": "7", 8 | "when": 1731495307444, 9 | "tag": "0000_eager_silver_samurai", 10 | "breakpoints": true 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/schemas/deletedUsers.ts: -------------------------------------------------------------------------------- 1 | import { pgTable, bigint, timestamp } from 'drizzle-orm/pg-core'; 2 | 3 | export const deletedUsers = pgTable('deleted_users', { 4 | id: bigint("id", { mode: "bigint" }).primaryKey(), 5 | delete_date: timestamp('delete_date').notNull().defaultNow(), 6 | }); -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/schemas/games.ts: -------------------------------------------------------------------------------- 1 | import { pgTable, integer, boolean } from 'drizzle-orm/pg-core'; 2 | 3 | export const games = pgTable('games', { 4 | id: integer('id').primaryKey(), 5 | is_selectable: boolean('is_selectable').default(false) 6 | }); -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/schemas/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./deletedUsers" 2 | export * from "./games" 3 | export * from "./libraries" 4 | export * from "./players" 5 | export * from "./steamders" 6 | export * from "./steamdersPlayers" 7 | export * from "./relations" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/schemas/libraries.ts: -------------------------------------------------------------------------------- 1 | import { pgTable, uuid, integer, bigint, boolean } from "drizzle-orm/pg-core"; 2 | import { players, games } from "."; 3 | 4 | export const libraries = pgTable("libraries", { 5 | id: uuid("id").primaryKey().defaultRandom(), 6 | player_id: bigint("player_id", { mode: "bigint" }).references(() => players.id, { onDelete: "cascade" }), 7 | game_id: integer("game_id").references(() => games.id), 8 | hidden: boolean("hidden").default(false) 9 | }); -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/schemas/players.ts: -------------------------------------------------------------------------------- 1 | import { pgTable, bigint, varchar } from "drizzle-orm/pg-core"; 2 | 3 | export const players = pgTable("players", { 4 | id: bigint("id", { mode: "bigint" }).primaryKey(), 5 | avatar_hash: varchar("avatar_hash", { length: 255 }).unique(), 6 | username: varchar("username", { length: 255 }), 7 | profileurl: varchar("profileurl", { length: 255 }).unique() 8 | }); -------------------------------------------------------------------------------- /packages/server/src/infrastructure/data/schemas/steamdersPlayers.ts: -------------------------------------------------------------------------------- 1 | import { pgTable, primaryKey, bigint, uuid } from "drizzle-orm/pg-core"; 2 | import { players, steamders } from "."; 3 | 4 | export const steamdersPlayers = pgTable('steamders_players', { 5 | player_id: bigint('player_id', { mode: 'bigint'}).references(() => players.id, { onDelete: 'cascade' }), 6 | steamder_id: uuid('steamder_id').references(() => steamders.id, { onDelete: 'cascade' }) 7 | }, (steamder_player) => { 8 | return { 9 | pk: primaryKey({columns: [steamder_player.player_id, steamder_player.steamder_id]}) 10 | } 11 | }); -------------------------------------------------------------------------------- /packages/server/src/infrastructure/repositories/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./PlayerRepository" 2 | export * from "./LibraryRepository" 3 | export * from "./SteamderRepository" 4 | export * from "./DeletedUserRepository" 5 | export * from "./SteamderPlayerRepository" 6 | export * from "./GameRepository" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./logout" 2 | export * from "./me" 3 | export * from "./steam" 4 | export * from "./steamCallback" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/auth/logout.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; 2 | import { APIResponse } from "@utils//response"; 3 | import { logout } from "@services/authService"; 4 | 5 | /** 6 | * Logs out a user. 7 | * 8 | * @param fastify - The Fastify instance. 9 | * @param request - The Fastify request object. 10 | * @param reply - The Fastify reply object. 11 | * @returns A Promise that resolves to an API response indicating successful logout. 12 | */ 13 | export const logoutUser = (fastify: FastifyInstance) => async (request: FastifyRequest, reply: FastifyReply) => { 14 | logout(fastify, reply, request); 15 | return APIResponse(reply, null, 'logged_out', 200); 16 | }; -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/auth/steam.ts: -------------------------------------------------------------------------------- 1 | import { FastifyReply, FastifyRequest } from "fastify"; 2 | import { APIResponse } from "@utils//response"; 3 | 4 | /** 5 | * Handles the steam endpoint. 6 | * 7 | * @param request - The FastifyRequest object. 8 | * @param reply - The FastifyReply object. 9 | * @returns A Promise that resolves to an API response. 10 | */ 11 | export const steam = async (request: FastifyRequest, reply: FastifyReply) => { 12 | if (!request.user) 13 | return APIResponse(reply, null, "logged_in_to_view_profile", 401); 14 | return APIResponse(reply, request.user, "logged_in", 200); 15 | }; -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/auth/steamCallback.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; 2 | import { login } from "@services/authService"; 3 | 4 | /** 5 | * Handles the Steam callback for authentication. 6 | * 7 | * @param fastify - The Fastify instance. 8 | * @param request - The Fastify request object. 9 | * @param reply - The Fastify reply object. 10 | * @returns A promise that resolves to the result of the login operation. 11 | */ 12 | export const steamCallback = (fastify: FastifyInstance) => async (request: FastifyRequest, reply: FastifyReply) => { 13 | return login(fastify, reply, request); 14 | } -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/debug/getAllEnv.ts: -------------------------------------------------------------------------------- 1 | import { FastifyReply, FastifyRequest } from "fastify"; 2 | import { FastifyInstance } from "fastify/types/instance"; 3 | 4 | /** 5 | * [DEBUG - Works only in development] Retrieves all environment variables. 6 | * 7 | * @param request - The Fastify request object. 8 | * @param reply - The Fastify reply object. 9 | */ 10 | export const getAllEnvVariables = ( 11 | request: FastifyRequest, 12 | reply: FastifyReply 13 | ) => { 14 | const fastify = request.server as FastifyInstance; 15 | reply.send({ config: fastify.config }); 16 | }; -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/debug/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./getAllEnv" 2 | export * from "./truncate" 3 | export * from "./seed" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/global/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./stats" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./auth" 2 | export * from "./debug" 3 | export * from "./global" 4 | export * from "./player" 5 | export * from "./steamder" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/library/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./get"; 2 | export * from "./update"; -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/player/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./delete" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/steamder/count.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; 2 | import { APIResponse } from "@utils/response"; 3 | import { countAvailableSteamders } from "@repositories"; 4 | 5 | export async function countSteamders(request: FastifyRequest, reply: FastifyReply): Promise { 6 | const fastify = request.server as FastifyInstance; 7 | 8 | try { 9 | const numberOfSteamders = await countAvailableSteamders(fastify); 10 | return APIResponse(reply, { count: numberOfSteamders }, 'OK', 200); 11 | } catch (err) { 12 | fastify.log.error(err); 13 | return APIResponse(reply, null, err as string, 500); 14 | } 15 | } -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/controllers/steamder/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./join" 2 | export * from "./leave" 3 | export * from "./kick" 4 | export * from "./count" 5 | export * from "./get" 6 | export * from "./paginate"; 7 | export * from "./create"; -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/routes/global.route.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance } from 'fastify'; 2 | import { 3 | getStats 4 | } from '@controllers/global'; 5 | 6 | export default async function globalRouter(fastify: FastifyInstance) { 7 | fastify.register(async function (fastify) { 8 | // Route to get the global statistics of the application (number of games, users, etc.) 9 | fastify.get('/stats', getStats); // :GET /global/stats 10 | }); 11 | } -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/routes/library.route.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-multi-spaces */ 2 | import { FastifyInstance } from 'fastify'; 3 | import { getLibraryOpts, updateHiddenGamesOpts } from '../options/library.option'; 4 | 5 | export default async function playerRouter(fastify: FastifyInstance) { 6 | fastify.register(async function (fastify) { 7 | fastify.route(getLibraryOpts); // :GET / 8 | fastify.route(updateHiddenGamesOpts); // :PATCH / 9 | }); 10 | } -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/routes/player.route.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-multi-spaces */ 2 | import { FastifyInstance } from 'fastify'; 3 | import { deleteUserOpts, getSteamLibraryOpts } from '../options/player.option'; 4 | 5 | export default async function playerRouter(fastify: FastifyInstance) { 6 | fastify.register(async function (fastify) { 7 | fastify.route(deleteUserOpts); // :DELETE /players 8 | fastify.route(getSteamLibraryOpts); // :GET /library-checker 9 | }); 10 | } -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/validations/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./kickValidation" 2 | export * from "./steamderValidation" 3 | export * from "./typeValidation" -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/validations/kickValidation.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const kickSchema = z.object({ 4 | steamderId: z.string().uuid({ message: "invalid_steamder_id" }), 5 | playerId: z.string().uuid({ message: "invalid_player_id" }), 6 | }); 7 | -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/validations/steamderValidation.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const steamderSchema = z.object({ 4 | name: z 5 | .string() 6 | .transform((value) => (value === "" || value === null || !value || value === undefined ? "Steamder" : value)) 7 | .refine((value) => value.length >= 3 && value.length <= 40, { 8 | message: "invalid_name", 9 | }), 10 | isPrivate: z.boolean().default(false), 11 | }); 12 | 13 | export const paginateSchema = z.object({ 14 | offset: z 15 | .number() 16 | .min(0, { message: "invalid_offset" }) 17 | .max(1000, { message: "invalid_offset" }), 18 | limit: z 19 | .number() 20 | .min(1, { message: "invalid_limit" }) 21 | .max(100, { message: "invalid_limit" }), 22 | }); 23 | -------------------------------------------------------------------------------- /packages/server/src/infrastructure/web/validations/typeValidation.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const uuidSchema = z.string().uuid({ message: "invalid_uuid" }); 4 | -------------------------------------------------------------------------------- /packages/server/src/plugins/cors.plugin.ts: -------------------------------------------------------------------------------- 1 | import { fastifyCors } from '@fastify/cors' 2 | 3 | export const corsPlugin = (fastify: any) => { 4 | return fastify.register(fastifyCors, { 5 | origin: fastify.config.ORIGIN, 6 | methods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE'], 7 | allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Origin', 'Accept'], 8 | credentials: true, 9 | preflightContinue: false, 10 | optionsSuccessStatus: 204 11 | }); 12 | }; -------------------------------------------------------------------------------- /packages/server/src/plugins/index.ts: -------------------------------------------------------------------------------- 1 | import { corsPlugin } from "./cors.plugin"; 2 | import { logger } from "./logger.plugin"; 3 | import { websocketPlugin } from "./websocket.plugin"; 4 | import { envPlugin } from "./env.plugin"; 5 | import { drizzlePlugin } from "./drizzle.plugin"; 6 | import { rateLimitPlugin } from "./ratelimit.plugin"; 7 | 8 | export { 9 | logger, 10 | corsPlugin, 11 | envPlugin, 12 | websocketPlugin, 13 | drizzlePlugin, 14 | rateLimitPlugin 15 | }; -------------------------------------------------------------------------------- /packages/server/src/plugins/logger.plugin.ts: -------------------------------------------------------------------------------- 1 | import pino from 'pino'; 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | 5 | const logsDir = path.resolve('./logs'); 6 | 7 | if (!fs.existsSync(logsDir)) { 8 | fs.mkdirSync(logsDir); 9 | } 10 | 11 | export const logger = pino({ 12 | level: process.env.NODE_ENV === 'production' ? 'info' : 'debug', 13 | timestamp: pino.stdTimeFunctions.isoTime, 14 | transport: { 15 | targets: [{ 16 | level: 'info', 17 | target: 'pino-pretty', 18 | options: { 19 | colorize: true, 20 | messageFormat: '{msg}', 21 | singleLine: true 22 | } 23 | }, { 24 | level: 'trace', 25 | target: 'pino/file', 26 | options: { 27 | destination: './logs/trace.log' 28 | } 29 | }] 30 | } 31 | }); -------------------------------------------------------------------------------- /packages/server/src/plugins/ratelimit.plugin.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance } from 'fastify'; 2 | import { fastifyRateLimit } from '@fastify/rate-limit'; 3 | 4 | export const rateLimitPlugin = (fastify: FastifyInstance) => { 5 | return fastify.register(fastifyRateLimit, { 6 | max: fastify.config.NODE_ENV === 'production' ? 45 : 1000, 7 | timeWindow: '1 minute' 8 | }); 9 | } -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/actions/index.ts: -------------------------------------------------------------------------------- 1 | import { swipe } from "./swipe"; 2 | import { leave } from "./leave"; 3 | import { kick } from "./kick"; 4 | import { unswipe } from "./unswipe"; 5 | import { update } from "./update"; 6 | import { allGamesSwitch } from "./allGamesSwitch"; 7 | 8 | export { swipe, leave, kick, unswipe, update, allGamesSwitch } -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/actions/unswipe.ts: -------------------------------------------------------------------------------- 1 | import { FastifyInstance } from "fastify"; 2 | import { Steamder } from "../types"; 3 | 4 | export const unswipe = async (fastify: FastifyInstance, steamder: Steamder, gameId: number) => { 5 | try { 6 | if (!steamder.started || steamder.ended) return; 7 | const swipedGames = steamder.swipedGames[gameId]; 8 | if (swipedGames) 9 | steamder.swipedGames[gameId] = swipedGames.filter((playerId: string) => playerId !== playerId); 10 | } catch (error) { 11 | fastify.log.error(`Error in 'unswipe' action: ${error}`); 12 | } 13 | } -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/types/IPlayerInfo.ts: -------------------------------------------------------------------------------- 1 | export interface PlayerInfo { 2 | avatar_hash: string; 3 | player_id: string; 4 | username: string; 5 | games: number[]; 6 | profileurl: string; 7 | } -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/types/ISteamder.ts: -------------------------------------------------------------------------------- 1 | import { PlayerInfo } from "./IPlayerInfo"; 2 | 3 | export interface Steamder { 4 | adminId: string; 5 | players: PlayerInfo[]; 6 | playerGames: Record; 7 | commonGames: number[]; 8 | swipedGames: Record; 9 | display_all_games: boolean; 10 | started: boolean; 11 | ended: boolean; 12 | winner?: number; 13 | endTime?: number; 14 | sockets: Set; 15 | } -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/types/index.ts: -------------------------------------------------------------------------------- 1 | import { PlayerInfo } from "./IPlayerInfo"; 2 | import { Steamder } from "./ISteamder"; 3 | 4 | export { PlayerInfo, Steamder }; -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/utils/calculateAllGames.ts: -------------------------------------------------------------------------------- 1 | import { Steamder } from "../types"; 2 | 3 | export const calculateAllGames = (steamderClients: Steamder) => { 4 | const allGamesSet = new Set(); 5 | 6 | Object.values(steamderClients.playerGames).forEach((games: any) => { 7 | games.forEach((game: number) => { 8 | allGamesSet.add(game); 9 | }); 10 | }); 11 | 12 | return Array.from(allGamesSet); 13 | }; 14 | -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/utils/checkGameEnd.ts: -------------------------------------------------------------------------------- 1 | import { Steamder } from "../types"; 2 | 3 | export const checkGameEnd = (gameId: number, steamder: Steamder): boolean => { 4 | if (steamder && steamder.started && !steamder.ended) { 5 | const swipedGames = steamder.swipedGames[gameId]; 6 | const players = steamder.players; 7 | 8 | const gameEnd = swipedGames?.length === players?.length; 9 | 10 | steamder.ended = gameEnd; 11 | if (steamder.ended) 12 | steamder.winner = gameId; 13 | return gameEnd; 14 | } 15 | return false; 16 | }; -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/utils/fillPlayerGamesList.ts: -------------------------------------------------------------------------------- 1 | import { PlayerInfo, Steamder } from "../types"; 2 | 3 | export const fillPlayerGamesList = (steamders: Map) => { 4 | // fill the playerGames list with the games of each player 5 | steamders.forEach((steamder: Steamder) => { 6 | steamder.players.forEach((player: PlayerInfo) => { 7 | steamder.playerGames[player.player_id] = player.games; 8 | }); 9 | }); 10 | } -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { calculateAllGames } from "./calculateAllGames"; 2 | import { updateCommonGames } from "./updateCommonGames"; 3 | import { checkCommonGames } from "./checkCommonGames"; 4 | import { deleteSteamder } from "./deleteSteamder"; 5 | import { checkGameEnd } from "./checkGameEnd"; 6 | import { fillPlayerGamesList } from "./fillPlayerGamesList"; 7 | import { startSteamder } from "./startSteamder"; 8 | import { createSteamder } from "./createSteamder"; 9 | import { joinSteamder } from "./joinSteamder"; 10 | 11 | export { 12 | calculateAllGames, 13 | updateCommonGames, 14 | checkCommonGames, 15 | deleteSteamder, 16 | checkGameEnd, 17 | fillPlayerGamesList, 18 | startSteamder, 19 | createSteamder, 20 | joinSteamder 21 | }; 22 | -------------------------------------------------------------------------------- /packages/server/src/plugins/ws/utils/updateCommonGames.ts: -------------------------------------------------------------------------------- 1 | import { Steamder } from "../types"; 2 | 3 | export const updateCommonGames = (steamder: Steamder) => { 4 | const playerIds = Object.keys(steamder.playerGames); 5 | 6 | let commonGamesSet = new Set(steamder.playerGames[playerIds[0]]); 7 | 8 | playerIds.slice(1).forEach((playerId) => { 9 | const gamesSet = new Set(steamder.playerGames[playerId]); 10 | commonGamesSet = new Set( 11 | [...commonGamesSet].filter((game) => gamesSet.has(game)) 12 | ); 13 | }); 14 | const common_games = Array.from(commonGamesSet); 15 | steamder.commonGames = common_games; 16 | }; 17 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages : 2 | - 'packages/**' --------------------------------------------------------------------------------