Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add price tax #89

Merged
merged 48 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
ea41d7e
feat: add p-4 to register and sign distribution pages
Goncalo-Marques Dec 24, 2024
8dcee3c
fix: readd brightness on hover
Goncalo-Marques Dec 24, 2024
278f5d1
feat: remove redundant information
Goncalo-Marques Dec 24, 2024
94150fb
feat: add terms page
Goncalo-Marques Dec 24, 2024
294d8ff
refactor: rename terms
Goncalo-Marques Dec 24, 2024
aa5e630
feat: add cookie policy
Goncalo-Marques Dec 24, 2024
6521175
feat: add privacy policy
Goncalo-Marques Dec 24, 2024
c146373
feat: update layout
Goncalo-Marques Dec 24, 2024
e659b7c
chore: remove todo
Goncalo-Marques Dec 24, 2024
7c319a0
chore: add gdpr info
Goncalo-Marques Dec 24, 2024
7c8fe13
refactor: change gray for consistency
Goncalo-Marques Dec 24, 2024
3365274
refactor: move error component
Goncalo-Marques Dec 24, 2024
28d4a3f
feat: add under construction page
Goncalo-Marques Dec 24, 2024
074069d
feat: change dev tools button position
Goncalo-Marques Dec 25, 2024
d94c4ce
feat: add mb to component
Goncalo-Marques Dec 25, 2024
1ded31a
feat: readd wishlist
Goncalo-Marques Dec 25, 2024
44c32dc
feat: add tooltip
Goncalo-Marques Dec 25, 2024
4e5a2e9
fix: format gen file
Goncalo-Marques Dec 25, 2024
63d277b
Merge branch 'web/add-not-implemented-page' of github.com:GOOFR-Group…
Goncalo-Marques Dec 25, 2024
a4e7802
fix_ lint
Goncalo-Marques Dec 25, 2024
3abc1e8
feat: add missing footer links
Goncalo-Marques Dec 25, 2024
0673ed9
feat: update server secondary sort field
Goncalo-Marques Dec 25, 2024
af21cba
fix: update recommended games to avoid duplicate publishers
Goncalo-Marques Dec 25, 2024
0cc9800
feat: update cover image
Goncalo-Marques Dec 26, 2024
b536cde
feat: add recommended games api
Goncalo-Marques Dec 26, 2024
5ff3d02
feat: update home page
Goncalo-Marques Dec 26, 2024
82a3fe4
refactor: optimize code
Goncalo-Marques Dec 26, 2024
c7b7c57
wip
Goncalo-Marques Dec 26, 2024
518cbd9
chore: fix lint issues
Goncalo-Marques Dec 26, 2024
12da226
feat: optimize under construction page
Goncalo-Marques Dec 26, 2024
38518ed
fix: correct tooltip
Goncalo-Marques Dec 26, 2024
76f33f6
Merge branch 'web/add-not-implemented-page' of github.com:GOOFR-Group…
Goncalo-Marques Dec 26, 2024
17ce92f
refactor: rename components
Goncalo-Marques Dec 26, 2024
512aafc
Merge branch 'web/add-not-implemented-page' of github.com:GOOFR-Group…
Goncalo-Marques Dec 26, 2024
4bae066
Merge branch 'main' of github.com:GOOFR-Group/gaming-store into web/1…
Goncalo-Marques Dec 26, 2024
e7233e5
chore: keep link consistency
Goncalo-Marques Dec 26, 2024
70105c8
feat: change game card size
Goncalo-Marques Dec 26, 2024
a6aad48
feat: change footer bg color
Goncalo-Marques Dec 26, 2024
1ba5e81
feat: add footer padding
Goncalo-Marques Dec 26, 2024
8557326
feat: add server tax
Goncalo-Marques Dec 26, 2024
6f82a83
feat: include tax
Goncalo-Marques Dec 26, 2024
8270bee
chore: optimize code
Goncalo-Marques Dec 26, 2024
8b8bedd
Merge branch 'web/18-system-allows-a-player-to-browse-the-game-catalo…
Goncalo-Marques Dec 26, 2024
e1978cf
fix: correct edit round
Goncalo-Marques Dec 26, 2024
490d3e3
fix: correct about game visualization
Goncalo-Marques Dec 26, 2024
bae4cbb
Merge branch 'main' of github.com:GOOFR-Group/gaming-store into feat/…
Goncalo-Marques Dec 26, 2024
c146a6e
chore: optimize code
Goncalo-Marques Dec 27, 2024
26415c4
refactor: remove unnecessary spaces
Goncalo-Marques Dec 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions server/internal/domain/user_cart.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package domain

import "errors"

const (
Tax = 0.23 // Defines the tax applied to the user cart purchase. It represents a number between 0 and 1.
)

// User cart errors.
var (
ErrUserCartGameAlreadyExists = errors.New("user cart game already exists") // Returned when a user cart game association already exists.
Expand Down
2 changes: 1 addition & 1 deletion server/internal/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type DataStore interface {
CreateUserCartGame(ctx context.Context, tx pgx.Tx, userID, gameID uuid.UUID) error
ListUserCart(ctx context.Context, tx pgx.Tx, userID uuid.UUID, filter domain.UserCartPaginatedFilter) (domain.PaginatedResponse[domain.Game], error)
DeleteUserCartGame(ctx context.Context, tx pgx.Tx, userID, gameID uuid.UUID) error
PurchaseUserCart(ctx context.Context, tx pgx.Tx, userID uuid.UUID) error
PurchaseUserCart(ctx context.Context, tx pgx.Tx, userID uuid.UUID, tax float64) error

ListUserLibrary(ctx context.Context, tx pgx.Tx, userID uuid.UUID, filter domain.UserLibraryPaginatedFilter) (domain.PaginatedResponse[domain.Game], error)
ExistsUserLibraryGame(ctx context.Context, tx pgx.Tx, userID, gameID uuid.UUID) (bool, error)
Expand Down
4 changes: 3 additions & 1 deletion server/internal/service/user_cart.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ func (s *service) PurchaseUserCart(ctx context.Context, userID uuid.UUID) error
totalPrice += float64(game.Price)
}

totalPrice = totalPrice * (1 + domain.Tax)

newUserBalance := user.Balance - totalPrice
if newUserBalance < 0 {
return domain.ErrUserBalanceInsufficient
Expand All @@ -221,7 +223,7 @@ func (s *service) PurchaseUserCart(ctx context.Context, userID uuid.UUID) error
return err
}

err = s.dataStore.PurchaseUserCart(ctx, tx, userID)
err = s.dataStore.PurchaseUserCart(ctx, tx, userID, domain.Tax)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions server/internal/store/data/user_cart.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (s *store) DeleteUserCartGame(ctx context.Context, tx pgx.Tx, userID, gameI

// PurchaseUserCart executes a query to delete all the user cart games and insert them in the user library with the
// specified identifier. It also stores an invoice for the purchased games.
func (s *store) PurchaseUserCart(ctx context.Context, tx pgx.Tx, userID uuid.UUID) error {
func (s *store) PurchaseUserCart(ctx context.Context, tx pgx.Tx, userID uuid.UUID, tax float64) error {
_, err := tx.Exec(ctx, `
WITH purchasing_user AS (
SELECT id, vatin
Expand All @@ -170,11 +170,12 @@ func (s *store) PurchaseUserCart(ctx context.Context, tx pgx.Tx, userID uuid.UUI
(SELECT id FROM invoice),
game_id,
(SELECT price FROM games WHERE id = game_id),
0,
$2,
(SELECT vatin FROM publishers WHERE id = (SELECT publisher_id FROM games WHERE id = game_id))
FROM purchased_games
`,
userID,
tax,
)
if err != nil {
switch constraintNameFromError(err) {
Expand Down
5 changes: 3 additions & 2 deletions web/src/components/distribute/games/form/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import { decodeTokenPayload, getToken } from "@/lib/auth";
import {
LANGUAGES,
MISSING_VALUE_SYMBOL,
TAX,
TOAST_MESSAGES,
} from "@/lib/constants";
import { Conflict, ContentTooLarge } from "@/lib/errors";
Expand Down Expand Up @@ -271,7 +272,7 @@ export function GameForm(props: GameProps) {
if (props.mode === "add") {
const newGame: NewGame = {
title: data.title,
price: data.price,
price: data.price / (1 + TAX),
isActive: data.isActive,
description: data.description,
ageRating: data.ageRating,
Expand Down Expand Up @@ -325,7 +326,7 @@ export function GameForm(props: GameProps) {

const editableGame: EditableGame = {
title: data.title,
price: data.price,
price: data.price / (1 + TAX),
isActive: data.isActive,
description: data.description,
ageRating: data.ageRating,
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/game.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MISSING_VALUE_SYMBOL } from "@/lib/constants";
import { MISSING_VALUE_SYMBOL, TAX } from "@/lib/constants";
import { formatCurrency } from "@/lib/utils";

export function Game(props: {
Expand All @@ -24,7 +24,7 @@ export function Game(props: {
<div className="mt-2 flex items-center gap-2 flex-wrap">
<p>
{!Number.isNaN(Number(props.price))
? formatCurrency(props.price)
? formatCurrency(props.price, TAX)
: MISSING_VALUE_SYMBOL}
</p>
</div>
Expand Down
6 changes: 6 additions & 0 deletions web/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,9 @@ export const TO_BE_ANNOUNCED = "To be announced";
* Minimum age at which the user can be registered on the platform.
*/
export const MINIMUM_USER_AGE = 16;

/**
* Tax applied to the user cart purchase.
* It represents a number between 0 and 1.
*/
export const TAX = 0.23;
4 changes: 2 additions & 2 deletions web/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ export function cn(...classes: ClassValue[]) {
* @param value Value to be formatted.
* @returns Formatted value.
*/
export function formatCurrency(value: number) {
export function formatCurrency(value: number, tax: number) {
const currencyFormat = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
});
return currencyFormat.format(value);
return currencyFormat.format(value * (1 + tax));
}

/**
Expand Down
18 changes: 10 additions & 8 deletions web/src/routes/_layout/cart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { TAX } from "@/lib/constants";
import { cartQueryKey } from "@/lib/query-keys";
import { formatCurrency } from "@/lib/utils";

function cartQueryOptions() {
return queryOptions({
Expand Down Expand Up @@ -47,16 +49,16 @@ function Component() {
}

const subtotal = cartItems.reduce((sum, item) => sum + item.price, 0);
const tax = subtotal * 0.1; // Assuming 10% tax
const total = subtotal + tax;

return (
<div className="container mx-auto px-4 py-8">
<div className="flex justify-between items-center mb-8">
<h1 className="text-3xl font-bold">Your Cart</h1>
<div className="text-lg">
Account Balance:{" "}
<span className="font-semibold">€{accountBalance.toFixed(2)}</span>
<span className="font-semibold">
{formatCurrency(accountBalance, 0)}{" "}
</span>
</div>
</div>
<div className="flex flex-wrap-reverse gap-8">
Expand All @@ -77,7 +79,7 @@ function Component() {
<p className="text-sm text-gray-300">{item.developer}</p>
</div>
<p className="text-lg font-semibold">
€{item.price.toFixed(2)}
{formatCurrency(item.price, TAX)}
</p>
</div>
<div className="flex-1 flex flex-wrap items-center justify-end mt-2">
Expand Down Expand Up @@ -110,15 +112,15 @@ function Component() {
<CardContent className="space-y-2">
<div className="flex justify-between">
<span>Subtotal</span>
<span>€{subtotal.toFixed(2)}</span>
<span>{formatCurrency(subtotal, 0)}</span>
</div>
<div className="flex justify-between">
<span>Tax</span>
<span>€{tax.toFixed(2)}</span>
<span>Tax ({TAX * 100}%)</span>
<span>{formatCurrency(subtotal * TAX, 0)}</span>
</div>
<div className="flex justify-between font-bold">
<span>Total</span>
<span>€{total.toFixed(2)}</span>
<span>{formatCurrency(subtotal, TAX)}</span>
</div>
</CardContent>
<CardFooter>
Expand Down
22 changes: 16 additions & 6 deletions web/src/routes/distribute/_layout/games/$gameId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from "@/components/ui/tooltip";
import { getPublisherGame } from "@/lib/api";
import { decodeTokenPayload, getToken } from "@/lib/auth";
import { MISSING_VALUE_SYMBOL } from "@/lib/constants";
import { MISSING_VALUE_SYMBOL, TAX, TO_BE_ANNOUNCED } from "@/lib/constants";
import { BadRequest, NotFound } from "@/lib/errors";
import { gameQueryKey } from "@/lib/query-keys";
import { formatCurrency, getLanguageName } from "@/lib/utils";
Expand Down Expand Up @@ -115,16 +115,26 @@ function Component() {
</CardHeader>
<CardContent className="flex-1 space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h3 className="font-semibold mb-1">Price</h3>
<p>{formatCurrency(game.price)}</p>
<div className="grid grid-cols-2 w-fit gap-2">
<div>
<h3 className="font-semibold mb-1"> Price </h3>
<p> {formatCurrency(game.price, TAX)} </p>
</div>
<div>
<h3 className="font-semibold mb-1 text-muted-foreground">
(Tax {TAX * 100}%)
</h3>
<p className="text-muted-foreground">
{formatCurrency(game.price, 0)}
</p>
</div>
</div>
<div>
<h3 className="font-semibold mb-1">Release Date</h3>
<p>
{"releaseDate" in game
? format(game.releaseDate, "dd/MM/yyyy")
: "To be announced"}
: TO_BE_ANNOUNCED}
</p>
</div>
<div>
Expand Down Expand Up @@ -176,7 +186,7 @@ function Component() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h3 className="text-lg font-semibold mb-2">About the Game</h3>
<p>{game.description}</p>
<p className="whitespace-pre-wrap">{game.description}</p>
</div>

<div>
Expand Down
3 changes: 2 additions & 1 deletion web/src/routes/distribute/_layout/games_/$gameId/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from "@/components/ui/card";
import { getPublisherGame } from "@/lib/api";
import { decodeTokenPayload, getToken } from "@/lib/auth";
import { TAX } from "@/lib/constants";
import { BadRequest, NotFound } from "@/lib/errors";
import { gameQueryKey } from "@/lib/query-keys";

Expand Down Expand Up @@ -87,7 +88,7 @@ function Component() {
features: game.features,
tags: game.tags,
languages: game.languages,
price: game.price,
price: Math.round(game.price * (1 + TAX) * 100) / 100,
releaseDate:
"releaseDate" in game ? new Date(game.releaseDate) : undefined,
title: game.title,
Expand Down
Loading