Skip to content
This repository was archived by the owner on Feb 28, 2026. It is now read-only.

Commit af67a0a

Browse files
authored
Merge pull request #68 from WildCodeSchool/feature/lose-money
Feature/lose money
2 parents 20c0997 + 05e8fdd commit af67a0a

File tree

14 files changed

+359
-90
lines changed

14 files changed

+359
-90
lines changed

packages/backend/api/src/albums/albums.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ albumsRouter.post('/create', async (req: Request, res) => {
1212
});
1313
return;
1414
}
15-
const { artistHiredId, singleName, singleId, genreId } = req.body;
15+
const { artistHiredId, singleName, singleId, genreId, price } = req.body;
1616
try {
1717
if (!Number(artistHiredId)) {
1818
res.status(400).json({ error: 'artistId is required' });
@@ -40,6 +40,22 @@ albumsRouter.post('/create', async (req: Request, res) => {
4040
})
4141
.executeTakeFirst();
4242

43+
const moneyEarn = await db
44+
.selectFrom('albums')
45+
.select('money_earned')
46+
.where('artists_hired_id', '=', artistHiredId)
47+
.executeTakeFirst();
48+
49+
const newMoney = Number(moneyEarn?.money_earned) - price;
50+
51+
await db
52+
.updateTable('labels')
53+
.set((eb) => ({
54+
budget: eb('budget', '+', Number(newMoney)),
55+
}))
56+
.where('users_id', '=', userId)
57+
.execute();
58+
4359
await db
4460
.insertInto('singles_albums')
4561
.values(

packages/backend/api/src/artists-hired/artists-hired.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ artistsHiredRouter.post('/', async (req: Request, res) => {
8383
res.status(500).json({ error: 'Internal server error' });
8484
}
8585
});
86+
8687
function getArtistsHired(userId: number) {
8788
return db
8889
.selectFrom('users')

packages/backend/api/src/games/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import getLogosRouter from './get-logos';
66
import getStaffRouter from './get-staff';
77
import staffLabelsRouter from './get-staff-labels';
88
import getLabelInfoRouter from './label-info';
9+
import getPriceRouter from './price';
910
import postRegisterLabelRouter from './register-label';
1011
import staffHiredRouter from './staff-hired';
1112
import pointRouter from './update-point';
@@ -21,5 +22,6 @@ gamesRouter.use(getStaffRouter);
2122
gamesRouter.use(staffHiredRouter);
2223
gamesRouter.use(staffLabelsRouter);
2324
gamesRouter.use(deleteStaffRouter);
25+
gamesRouter.use(getPriceRouter);
2426

2527
export default gamesRouter;

packages/backend/api/src/games/label-info.ts

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,54 @@ import { db } from '@app/backend-shared';
44

55
const getLabelInfoRouter = Router();
66

7+
function getInfoLabel(userId: number) {
8+
return db
9+
.selectFrom('users')
10+
.where('users.id', '=', Number(userId))
11+
.leftJoin('labels', 'labels.users_id', 'users.id')
12+
.leftJoin('logos', 'logos.id', 'labels.logos_id')
13+
.leftJoin('staff_label', 'staff_label.labels_id', 'labels.id')
14+
.leftJoin('staff', 'staff.id', 'staff_label.staff_id')
15+
.leftJoin('label_artists', 'label_artists.label_id', 'labels.id')
16+
.leftJoin(
17+
'artists_hired',
18+
'artists_hired.id',
19+
'label_artists.artists_hired_id',
20+
)
21+
.leftJoin('artists', 'artists.id', 'artists_hired.artists_id')
22+
.leftJoin(
23+
'crew_members_hired',
24+
'crew_members_hired.artists_id',
25+
'artists_hired.id',
26+
)
27+
.leftJoin(
28+
'crew_members',
29+
'crew_members.id',
30+
'crew_members_hired.crew_members_id',
31+
)
32+
.leftJoin('singles', 'singles.artists_hired_id', 'artists_hired.id')
33+
.leftJoin('singles_marketing', 'singles_marketing.singles_id', 'singles.id')
34+
.leftJoin('marketing', 'marketing.id', 'singles_marketing.marketing_id')
35+
.leftJoin('albums', 'albums.artists_hired_id', 'artists_hired.id')
36+
.leftJoin('albums_marketing', 'albums_marketing.albums_id', 'albums.id')
37+
.select([
38+
'labels.id',
39+
'labels.name',
40+
'logos.logo_img',
41+
'labels.notoriety',
42+
'labels.budget',
43+
db.fn.sum('staff.exp_value').as('staff_xp'),
44+
db.fn.sum('artists.exp_value').as('artists_xp'),
45+
db.fn.sum('crew_members.exp_value').as('crew_xp'),
46+
db.fn.sum('albums.exp_value').as('albums_xp'),
47+
db.fn.sum('marketing.exp_value').as('marketing_xp'),
48+
db.fn.sum('singles.exp_value').as('singles_xp'),
49+
])
50+
.groupBy('labels.id')
51+
.execute();
52+
}
53+
export type InfoLabel = Awaited<ReturnType<typeof getInfoLabel>>[number];
54+
755
getLabelInfoRouter.get('/label', async (req: Request, res) => {
856
const userId = req.userId;
957
if (userId === undefined) {
@@ -14,55 +62,7 @@ getLabelInfoRouter.get('/label', async (req: Request, res) => {
1462
}
1563

1664
try {
17-
const xpData = await db
18-
.selectFrom('users')
19-
.where('users.id', '=', Number(userId))
20-
.leftJoin('labels', 'labels.users_id', 'users.id')
21-
.leftJoin('logos', 'logos.id', 'labels.logos_id')
22-
.leftJoin('staff_label', 'staff_label.labels_id', 'labels.id')
23-
.leftJoin('staff', 'staff.id', 'staff_label.staff_id')
24-
.leftJoin('label_artists', 'label_artists.label_id', 'labels.id')
25-
.leftJoin(
26-
'artists_hired',
27-
'artists_hired.id',
28-
'label_artists.artists_hired_id',
29-
)
30-
.leftJoin('artists', 'artists.id', 'artists_hired.artists_id')
31-
.leftJoin(
32-
'crew_members_hired',
33-
'crew_members_hired.artists_id',
34-
'artists_hired.id',
35-
)
36-
.leftJoin(
37-
'crew_members',
38-
'crew_members.id',
39-
'crew_members_hired.crew_members_id',
40-
)
41-
.leftJoin('singles', 'singles.artists_hired_id', 'artists_hired.id')
42-
.leftJoin(
43-
'singles_marketing',
44-
'singles_marketing.singles_id',
45-
'singles.id',
46-
)
47-
.leftJoin('marketing', 'marketing.id', 'singles_marketing.marketing_id')
48-
.leftJoin('albums', 'albums.artists_hired_id', 'artists_hired.id')
49-
.leftJoin('albums_marketing', 'albums_marketing.albums_id', 'albums.id')
50-
.select([
51-
'labels.id',
52-
'labels.name',
53-
'logos.logo_img',
54-
'labels.notoriety',
55-
'labels.budget',
56-
db.fn.sum('staff.exp_value').as('staff_xp'),
57-
db.fn.sum('artists.exp_value').as('artists_xp'),
58-
db.fn.sum('crew_members.exp_value').as('crew_xp'),
59-
db.fn.sum('albums.exp_value').as('albums_xp'),
60-
db.fn.sum('marketing.exp_value').as('marketing_xp'),
61-
db.fn.sum('singles.exp_value').as('singles_xp'),
62-
])
63-
.groupBy('labels.id')
64-
.execute();
65-
65+
const xpData = await getInfoLabel(userId);
6666
const labelData = xpData[0];
6767

6868
if (!Boolean(xpData)) {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import express from 'express';
2+
3+
import { db } from '@app/backend-shared';
4+
5+
const getPriceRouter = express.Router();
6+
function getPrice() {
7+
return db.selectFrom('price').select('price');
8+
}
9+
export type Price = Awaited<
10+
ReturnType<ReturnType<typeof getPrice>['execute']>
11+
>[number];
12+
getPriceRouter.get('/price-singles', async (req, res) => {
13+
try {
14+
const price = await getPrice()
15+
.where('name', '=', 'singles')
16+
.executeTakeFirst();
17+
res.json(price);
18+
} catch (_error) {
19+
res.json({
20+
ok: false,
21+
});
22+
}
23+
});
24+
getPriceRouter.get('/price-albums', async (req, res) => {
25+
try {
26+
const price = await getPrice()
27+
.where('name', '=', 'albums')
28+
.executeTakeFirst();
29+
res.json(price);
30+
} catch (_error) {
31+
res.json({
32+
ok: false,
33+
});
34+
}
35+
});
36+
getPriceRouter.get('/price-stats', async (req, res) => {
37+
try {
38+
const price = await getPrice()
39+
.where('name', '=', 'stats')
40+
.executeTakeFirst();
41+
res.json(price);
42+
} catch (_error) {
43+
res.json({
44+
ok: false,
45+
});
46+
}
47+
});
48+
49+
export default getPriceRouter;

packages/backend/api/src/games/update-point.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
1-
import express from 'express';
1+
import { type Request, Router } from 'express';
22

33
import { db } from '@app/backend-shared';
44

5-
const pointRouter = express.Router();
6-
pointRouter.post('/point', async (req, res) => {
7-
const { artistsHiredSkillsId, skills_id } = req.body;
5+
const pointRouter = Router();
6+
pointRouter.post('/point', async (req: Request, res) => {
7+
const userId = req.userId;
8+
if (userId === undefined) {
9+
res.json({
10+
ok: false,
11+
});
12+
return;
13+
}
14+
const { artistsHiredSkillsId, skills_id, price } = req.body;
815

916
try {
10-
const addPoint = await db
17+
await db
1118
.updateTable('artists_hired_skills')
1219
.set((eb) => ({
1320
grade: eb('grade', '+', 1),
1421
}))
1522
.where('artists_hired_skills.id', '=', artistsHiredSkillsId)
1623
.where('artists_hired_skills.skills_id', '=', skills_id)
1724
.execute();
18-
console.log(artistsHiredSkillsId, skills_id);
25+
26+
const budget = await db
27+
.updateTable('labels')
28+
.set((eb) => ({
29+
budget: eb('budget', '-', Number(price)),
30+
}))
31+
.where('users_id', '=', userId)
32+
.executeTakeFirst();
1933

2034
res.status(200).json({
2135
message: 'Point ajouté avec succès',

packages/backend/api/src/singles/singles.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ singlesRouter.get('/', async (req: Request, res) => {
9292
});
9393

9494
singlesRouter.post('/', async (req: Request, res) => {
95-
const { artistHiredId, singleName, genreId } = req.body;
95+
const { artistHiredId, singleName, genreId, price } = req.body;
9696

9797
const userId = req.userId;
9898
if (userId === undefined) {
@@ -121,6 +121,22 @@ singlesRouter.post('/', async (req: Request, res) => {
121121
})
122122
.execute();
123123

124+
const moneyEarn = await db
125+
.selectFrom('singles')
126+
.select('money_earned')
127+
.where('artists_hired_id', '=', artistHiredId)
128+
.executeTakeFirst();
129+
130+
const newMoney = Number(moneyEarn?.money_earned) - price;
131+
132+
await db
133+
.updateTable('labels')
134+
.set((eb) => ({
135+
budget: eb('budget', '+', Number(newMoney)),
136+
}))
137+
.where('users_id', '=', userId)
138+
.execute();
139+
124140
const milestones = await db
125141
.selectFrom('milestones')
126142
.leftJoin('artists_hired', 'artists_hired.milestones_id', 'milestones.id')
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { type Kysely, sql } from 'kysely';
2+
3+
import type { DB } from '@app/shared';
4+
5+
export async function up(db: Kysely<DB>): Promise<void> {
6+
// Migration code that update the database to the desired state.
7+
await db.transaction().execute(async (trx) => {
8+
await sql`
9+
ALTER TABLE price ADD name VARCHAR(255) NOT NULL;
10+
`.execute(trx);
11+
});
12+
}
13+
14+
export async function down(db: Kysely<DB>): Promise<void> {
15+
// Migration code that reverts the database to the previous state.
16+
await db.transaction().execute(async (trx) => {
17+
await sql`
18+
ALTER TABLE price DROP name;
19+
`.execute(trx);
20+
});
21+
}

packages/frontend/web/src/components/artist-profile-card.tsx

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
import type { ArtistHired } from '../../../../backend/api/src/artists-hired/artists-hired';
22
import type { Artist } from '../../../../backend/api/src/artists/artists';
3+
import type { Price } from '../../../../backend/api/src/games/price';
34
import AddButton from './add-button';
45

56
type ArtistProfileCardProps = {
67
readonly artist: Artist | ArtistHired;
78
readonly fetchArtistsHired?: (() => Promise<void>) | undefined;
89
readonly isAddButton?: boolean;
10+
readonly price?: Price;
11+
readonly isDisabled?: boolean;
12+
readonly fetchInfoLabel?: (() => Promise<void>) | undefined;
913
};
1014

1115
export default function ArtistProfileCard({
1216
artist,
1317
isAddButton,
1418
fetchArtistsHired,
19+
price,
20+
isDisabled,
21+
fetchInfoLabel,
1522
}: ArtistProfileCardProps) {
16-
async function addPoint(artistsHiredSkillsId: number, skills_id: number) {
23+
async function addPoint(
24+
artistsHiredSkillsId: number,
25+
skills_id: number,
26+
price: number,
27+
) {
1728
try {
1829
const response = await fetch(`/api/games/point`, {
1930
method: 'POST',
20-
body: JSON.stringify({ artistsHiredSkillsId, skills_id }),
31+
body: JSON.stringify({ artistsHiredSkillsId, skills_id, price }),
2132
headers: { 'Content-Type': 'application/json' },
2233
credentials: 'include',
2334
});
@@ -74,18 +85,26 @@ export default function ArtistProfileCard({
7485
{competence.grade}
7586
{' /25'}
7687
{(isAddButton ?? false) ? (
77-
<AddButton
78-
key={competence.artistsHiredSkillsId}
79-
onClick={() =>
80-
addPoint(
81-
competence.artistsHiredSkillsId ?? 0,
82-
competence.skillsId ?? 0,
83-
)
84-
}
85-
disabled={(competence.grade ?? 0) >= 25}
86-
>
87-
{'+'}
88-
</AddButton>
88+
<>
89+
<AddButton
90+
key={competence.artistsHiredSkillsId}
91+
onClick={() =>
92+
addPoint(
93+
competence.artistsHiredSkillsId ?? 0,
94+
competence.skillsId ?? 0,
95+
price?.price ?? 0,
96+
)
97+
}
98+
disabled={(competence.grade ?? 0) >= 25 || isDisabled}
99+
>
100+
{'+'}
101+
</AddButton>
102+
{price?.price != null && (
103+
<span className='ml-2 text-sm text-green-500'>
104+
{price.price} {'$'}
105+
</span>
106+
)}
107+
</>
89108
) : (
90109
''
91110
)}

0 commit comments

Comments
 (0)