@rpg-engine/long-bow 0.2.28 → 0.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/SkillProgressBar.d.ts +2 -0
- package/dist/components/SkillsContainer.d.ts +2 -0
- package/dist/components/TradingMenu/TrandingMenu.d.ts +12 -0
- package/dist/components/TradingMenu/itemComponent.d.ts +9 -0
- package/dist/components/TradingMenu/items.mock.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/long-bow.cjs.development.js +405 -388
- package/dist/long-bow.cjs.development.js.map +1 -1
- package/dist/long-bow.cjs.production.min.js +1 -1
- package/dist/long-bow.cjs.production.min.js.map +1 -1
- package/dist/long-bow.esm.js +405 -393
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/stories/ItemTradingComponent.stories.d.ts +5 -0
- package/dist/stories/TrandingMenu.stories.d.ts +5 -0
- package/package.json +2 -2
- package/src/components/Item/Inventory/ItemSlot.tsx +5 -3
- package/src/components/NPCDialog/.DS_Store +0 -0
- package/src/components/ScrollList.tsx +2 -1
- package/src/components/SkillProgressBar.tsx +4 -2
- package/src/components/SkillsContainer.tsx +8 -37
- package/src/components/TradingMenu/TrandingMenu.tsx +190 -0
- package/src/components/TradingMenu/itemComponent.tsx +158 -0
- package/src/components/TradingMenu/items.mock.ts +87 -0
- package/src/index.tsx +1 -0
- package/src/mocks/.DS_Store +0 -0
- package/src/stories/ItemTradingComponent.stories.tsx +39 -0
- package/src/stories/SkillProgressBar.stories.tsx +4 -0
- package/src/stories/SkillsContainer.stories.tsx +4 -0
- package/src/stories/TrandingMenu.stories.tsx +38 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react';
|
|
2
|
+
import { ITradeComponentProps } from '../components/TradingMenu/itemComponent';
|
|
3
|
+
declare const meta: Meta;
|
|
4
|
+
export default meta;
|
|
5
|
+
export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ITradeComponentProps>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react';
|
|
2
|
+
import { ITrandingMenu } from '../components/TradingMenu/TrandingMenu';
|
|
3
|
+
declare const meta: Meta;
|
|
4
|
+
export default meta;
|
|
5
|
+
export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ITrandingMenu>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpg-engine/long-bow",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.29",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@rollup/plugin-image": "^2.1.1",
|
|
86
|
-
"@rpg-engine/shared": "^0.5.
|
|
86
|
+
"@rpg-engine/shared": "^0.5.60",
|
|
87
87
|
"dayjs": "^1.11.2",
|
|
88
88
|
"fs-extra": "^10.1.0",
|
|
89
89
|
"lodash": "^4.17.21",
|
|
@@ -15,6 +15,7 @@ import { SpriteFromAtlas } from '../../shared/SpriteFromAtlas';
|
|
|
15
15
|
import { ItemTooltip } from '../Cards/ItemTooltip';
|
|
16
16
|
import { ErrorBoundary } from './ErrorBoundary';
|
|
17
17
|
import { generateContextMenu, IContextMenuItem } from './itemContainerHelper';
|
|
18
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
18
19
|
|
|
19
20
|
const EquipmentSlotSpriteByType: any = {
|
|
20
21
|
Neck: 'accessories/corruption-necklace.png',
|
|
@@ -104,7 +105,7 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
104
105
|
const element = [];
|
|
105
106
|
if (itemToRender?.texturePath) {
|
|
106
107
|
element.push(
|
|
107
|
-
<ErrorBoundary>
|
|
108
|
+
<ErrorBoundary key={itemToRender._id}>
|
|
108
109
|
<SpriteFromAtlas
|
|
109
110
|
key={itemToRender._id}
|
|
110
111
|
atlasIMG={atlasIMG}
|
|
@@ -133,7 +134,7 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
133
134
|
) {
|
|
134
135
|
const element = [];
|
|
135
136
|
element.push(
|
|
136
|
-
<ErrorBoundary>
|
|
137
|
+
<ErrorBoundary key={itemToRender._id}>
|
|
137
138
|
<SpriteFromAtlas
|
|
138
139
|
key={itemToRender._id}
|
|
139
140
|
atlasIMG={atlasIMG}
|
|
@@ -153,8 +154,9 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
153
154
|
return element;
|
|
154
155
|
} else {
|
|
155
156
|
return (
|
|
156
|
-
<ErrorBoundary>
|
|
157
|
+
<ErrorBoundary key={uuidv4()}>
|
|
157
158
|
<SpriteFromAtlas
|
|
159
|
+
key={uuidv4()}
|
|
158
160
|
atlasIMG={atlasIMG}
|
|
159
161
|
atlasJSON={atlasJSON}
|
|
160
162
|
spriteKey={EquipmentSlotSpriteByType[slotSpriteMask!]}
|
|
Binary file
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
import { DraggableContainer } from './DraggableContainer';
|
|
4
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
5
|
|
|
5
6
|
interface IListMenuOption {
|
|
6
7
|
id: string;
|
|
@@ -30,7 +31,7 @@ export const ListMenu: React.FC<IListMenuProps> = ({
|
|
|
30
31
|
<ListContainer className="rpgui-list-imp">
|
|
31
32
|
{options.map(params => (
|
|
32
33
|
<ListElement
|
|
33
|
-
key={
|
|
34
|
+
key={uuidv4()}
|
|
34
35
|
onClick={() => {
|
|
35
36
|
onSelected(params?.id);
|
|
36
37
|
}}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { getSPForLevel } from '@rpg-engine/shared';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
import atlasJSON from '../mocks/atlas/items/items.json';
|
|
5
|
-
import atlasIMG from '../mocks/atlas/items/items.png';
|
|
6
4
|
import { ErrorBoundary } from './Item/Inventory/ErrorBoundary';
|
|
7
5
|
import { SpriteFromAtlas } from './shared/SpriteFromAtlas';
|
|
8
6
|
import { SimpleProgressBar } from './SimpleProgressBar';
|
|
@@ -15,6 +13,8 @@ export interface ISkillProgressBarProps {
|
|
|
15
13
|
skillPointsToNextLevel?: number;
|
|
16
14
|
texturePath: string;
|
|
17
15
|
showSkillPoints?: boolean;
|
|
16
|
+
atlasJSON: any;
|
|
17
|
+
atlasIMG: any;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
|
|
@@ -24,6 +24,8 @@ export const SkillProgressBar: React.FC<ISkillProgressBarProps> = ({
|
|
|
24
24
|
skillPoints,
|
|
25
25
|
texturePath,
|
|
26
26
|
showSkillPoints = true,
|
|
27
|
+
atlasIMG,
|
|
28
|
+
atlasJSON,
|
|
27
29
|
}) => {
|
|
28
30
|
const spForNextLevel = getSPForLevel(level + 1);
|
|
29
31
|
|
|
@@ -9,6 +9,8 @@ import { SkillProgressBar } from './SkillProgressBar';
|
|
|
9
9
|
export interface ISkillContainerProps {
|
|
10
10
|
skill: ISkill;
|
|
11
11
|
onCloseButton: () => void;
|
|
12
|
+
atlasJSON: any;
|
|
13
|
+
atlasIMG: any;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
const skillProps = {
|
|
@@ -50,6 +52,8 @@ const skillProps = {
|
|
|
50
52
|
export const SkillsContainer: React.FC<ISkillContainerProps> = ({
|
|
51
53
|
onCloseButton,
|
|
52
54
|
skill,
|
|
55
|
+
atlasIMG,
|
|
56
|
+
atlasJSON,
|
|
53
57
|
}) => {
|
|
54
58
|
const onRenderSkillCategory = (
|
|
55
59
|
category: 'attributes' | 'combat' | 'crafting'
|
|
@@ -75,6 +79,8 @@ export const SkillsContainer: React.FC<ISkillContainerProps> = ({
|
|
|
75
79
|
Math.round(skillDetails.skillPointsToNextLevel) || 0
|
|
76
80
|
}
|
|
77
81
|
texturePath={value}
|
|
82
|
+
atlasIMG={atlasIMG}
|
|
83
|
+
atlasJSON={atlasJSON}
|
|
78
84
|
/>
|
|
79
85
|
);
|
|
80
86
|
}
|
|
@@ -100,6 +106,8 @@ export const SkillsContainer: React.FC<ISkillContainerProps> = ({
|
|
|
100
106
|
skillPoints={Math.round(skill.experience) || 0}
|
|
101
107
|
skillPointsToNextLevel={Math.round(skill.xpToNextLevel) || 0}
|
|
102
108
|
texturePath={'swords/broad-sword.png'}
|
|
109
|
+
atlasIMG={atlasIMG}
|
|
110
|
+
atlasJSON={atlasJSON}
|
|
103
111
|
/>
|
|
104
112
|
|
|
105
113
|
<p>Combat Skills</p>
|
|
@@ -121,43 +129,6 @@ export const SkillsContainer: React.FC<ISkillContainerProps> = ({
|
|
|
121
129
|
</SkillSplitDiv>
|
|
122
130
|
|
|
123
131
|
{onRenderSkillCategory('attributes')}
|
|
124
|
-
|
|
125
|
-
{/* <SkillSplitDiv>
|
|
126
|
-
<p>Magic Skills</p>
|
|
127
|
-
<hr className="golden" />
|
|
128
|
-
</SkillSplitDiv>
|
|
129
|
-
<SkillProgressBar
|
|
130
|
-
skillName={'Ice'}
|
|
131
|
-
bgColor={'red'}
|
|
132
|
-
level={skill?.ice?.level || 0}
|
|
133
|
-
skillPoints={skill?.ice?.skillPoints || 0}
|
|
134
|
-
skillPointsToNextLevel={skill?.ice?.skillPointsToNextLevel || 0}
|
|
135
|
-
texturePath={'spell-icons/freeze.png'}
|
|
136
|
-
/>
|
|
137
|
-
<SkillProgressBar
|
|
138
|
-
skillName={'Earth'}
|
|
139
|
-
bgColor={'red'}
|
|
140
|
-
level={skill?.earth?.level || 0}
|
|
141
|
-
skillPoints={skill?.earth?.skillPoints || 0}
|
|
142
|
-
skillPointsToNextLevel={skill?.earth?.skillPointsToNextLevel || 0}
|
|
143
|
-
texturePath={'spell-icons/earth-barrier.png'}
|
|
144
|
-
/>
|
|
145
|
-
<SkillProgressBar
|
|
146
|
-
skillName={'Air'}
|
|
147
|
-
bgColor={'red'}
|
|
148
|
-
level={skill?.air?.level || 0}
|
|
149
|
-
skillPoints={skill?.air?.skillPoints || 0}
|
|
150
|
-
skillPointsToNextLevel={skill?.air?.skillPointsToNextLevel || 0}
|
|
151
|
-
texturePath={'spell-icons/poison-tornado.png'}
|
|
152
|
-
/>
|
|
153
|
-
<SkillProgressBar
|
|
154
|
-
skillName={'Water'}
|
|
155
|
-
bgColor={'red'}
|
|
156
|
-
level={skill?.water?.level || 0}
|
|
157
|
-
skillPoints={skill?.water?.skillPoints || 0}
|
|
158
|
-
skillPointsToNextLevel={skill?.water?.skillPointsToNextLevel || 0}
|
|
159
|
-
texturePath={'spell-icons/tsunami.png'}
|
|
160
|
-
/> */}
|
|
161
132
|
</SkillsDraggableContainer>
|
|
162
133
|
);
|
|
163
134
|
};
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { DraggableContainer } from '../DraggableContainer';
|
|
4
|
+
import { RPGUIContainerTypes } from '../RPGUIContainer';
|
|
5
|
+
import { Button, ButtonTypes } from '../Button';
|
|
6
|
+
import { ItemTradingComponent } from './itemComponent';
|
|
7
|
+
import { ITransactionItem, TradeTransactionType } from '@rpg-engine/shared';
|
|
8
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
9
|
+
export interface ITrandingMenu {
|
|
10
|
+
traderItems: ITransactionItem[];
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
type: TradeTransactionType;
|
|
13
|
+
atlasJSON: any;
|
|
14
|
+
atlasIMG: any;
|
|
15
|
+
characterAvailableGold: number;
|
|
16
|
+
onChangeTraderItems: (traderItems: ITransactionItem[]) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const TrandingMenu: React.FC<ITrandingMenu> = ({
|
|
20
|
+
traderItems,
|
|
21
|
+
onClose,
|
|
22
|
+
type,
|
|
23
|
+
atlasJSON,
|
|
24
|
+
atlasIMG,
|
|
25
|
+
characterAvailableGold,
|
|
26
|
+
onChangeTraderItems,
|
|
27
|
+
}) => {
|
|
28
|
+
const [sum, setSum] = useState(0);
|
|
29
|
+
let newSumArray = 0;
|
|
30
|
+
const updateChartTotals = (item: ITransactionItem) => {
|
|
31
|
+
const itemIndex = traderItems.findIndex(
|
|
32
|
+
itemArray => itemArray.itemId === item.itemId
|
|
33
|
+
);
|
|
34
|
+
traderItems[itemIndex] = item;
|
|
35
|
+
|
|
36
|
+
traderItems.forEach(item => {
|
|
37
|
+
if (item.qty) newSumArray += item.qty * item.price;
|
|
38
|
+
setSum(newSumArray);
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (onChangeTraderItems) {
|
|
44
|
+
onChangeTraderItems(traderItems);
|
|
45
|
+
}
|
|
46
|
+
}, [traderItems]);
|
|
47
|
+
const Capitalize = (word: string) => {
|
|
48
|
+
return word[0].toUpperCase() + word.substring(1);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<TradingMenuDraggableContainer
|
|
53
|
+
type={RPGUIContainerTypes.Framed}
|
|
54
|
+
onCloseButton={() => {
|
|
55
|
+
if (onClose) onClose();
|
|
56
|
+
}}
|
|
57
|
+
width="500px"
|
|
58
|
+
cancelDrag=".equipment-container-body .arrow-selector"
|
|
59
|
+
>
|
|
60
|
+
<>
|
|
61
|
+
<div style={{ width: '100%' }}>
|
|
62
|
+
<Title>{Capitalize(type)}</Title>
|
|
63
|
+
<hr className="golden" />
|
|
64
|
+
</div>
|
|
65
|
+
<TrandingComponentScrollWrapper>
|
|
66
|
+
{traderItems.map(tradeItem => (
|
|
67
|
+
<ItemWrapper key={uuidv4()}>
|
|
68
|
+
<ItemTradingComponent
|
|
69
|
+
key={uuidv4()}
|
|
70
|
+
atlasIMG={atlasIMG}
|
|
71
|
+
atlasJSON={atlasJSON}
|
|
72
|
+
updateChartTotals={updateChartTotals}
|
|
73
|
+
traderItem={tradeItem}
|
|
74
|
+
/>
|
|
75
|
+
</ItemWrapper>
|
|
76
|
+
))}
|
|
77
|
+
</TrandingComponentScrollWrapper>
|
|
78
|
+
<GoldWrapper>
|
|
79
|
+
<p>Available Gold:</p>
|
|
80
|
+
<p>${characterAvailableGold}</p>
|
|
81
|
+
</GoldWrapper>
|
|
82
|
+
<TotalWrapper>
|
|
83
|
+
<p>Total:</p>
|
|
84
|
+
<p>${sum}</p>
|
|
85
|
+
</TotalWrapper>
|
|
86
|
+
{sum > characterAvailableGold ? (
|
|
87
|
+
<AlertWrapper>
|
|
88
|
+
<p> Sorry, not enough money.</p>
|
|
89
|
+
</AlertWrapper>
|
|
90
|
+
) : (
|
|
91
|
+
<GoldWrapper>
|
|
92
|
+
<p>Final Gold:</p>
|
|
93
|
+
<p>${characterAvailableGold - sum}</p>
|
|
94
|
+
</GoldWrapper>
|
|
95
|
+
)}
|
|
96
|
+
|
|
97
|
+
<ButtonWrapper>
|
|
98
|
+
<Button
|
|
99
|
+
buttonType={ButtonTypes.RPGUIButton}
|
|
100
|
+
disabled={sum > characterAvailableGold}
|
|
101
|
+
>
|
|
102
|
+
Confirm
|
|
103
|
+
</Button>
|
|
104
|
+
<Button buttonType={ButtonTypes.RPGUIButton}>Cancel</Button>
|
|
105
|
+
</ButtonWrapper>
|
|
106
|
+
</>
|
|
107
|
+
</TradingMenuDraggableContainer>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const TradingMenuDraggableContainer = styled(DraggableContainer)`
|
|
112
|
+
.container-close {
|
|
113
|
+
top: 10px;
|
|
114
|
+
right: 10px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.quest-title {
|
|
118
|
+
text-align: left;
|
|
119
|
+
margin-left: 44px;
|
|
120
|
+
margin-top: 20px;
|
|
121
|
+
color: yellow;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.quest-desc {
|
|
125
|
+
margin-top: 12px;
|
|
126
|
+
margin-left: 44px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.rpgui-progress {
|
|
130
|
+
min-width: 80%;
|
|
131
|
+
margin: 0 auto;
|
|
132
|
+
}
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
const Title = styled.h1`
|
|
136
|
+
z-index: 22;
|
|
137
|
+
font-size: 0.6rem;
|
|
138
|
+
color: yellow !important;
|
|
139
|
+
`;
|
|
140
|
+
|
|
141
|
+
const TrandingComponentScrollWrapper = styled.div`
|
|
142
|
+
overflow-y: scroll;
|
|
143
|
+
height: 500px;
|
|
144
|
+
width: 100%;
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
const ItemWrapper = styled.div`
|
|
148
|
+
width: 80%;
|
|
149
|
+
margin: auto;
|
|
150
|
+
display: flex;
|
|
151
|
+
justify-content: space-between;
|
|
152
|
+
`;
|
|
153
|
+
|
|
154
|
+
const TotalWrapper = styled.div`
|
|
155
|
+
width: 80%;
|
|
156
|
+
display: flex;
|
|
157
|
+
margin: auto;
|
|
158
|
+
justify-content: space-between;
|
|
159
|
+
height: 20px;
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
const GoldWrapper = styled.div`
|
|
163
|
+
width: 80%;
|
|
164
|
+
display: flex;
|
|
165
|
+
margin: auto;
|
|
166
|
+
justify-content: space-between;
|
|
167
|
+
height: 20px;
|
|
168
|
+
p {
|
|
169
|
+
color: yellow !important;
|
|
170
|
+
}
|
|
171
|
+
`;
|
|
172
|
+
|
|
173
|
+
const AlertWrapper = styled.div`
|
|
174
|
+
width: 80%;
|
|
175
|
+
display: flex;
|
|
176
|
+
margin: auto;
|
|
177
|
+
justify-content: center;
|
|
178
|
+
height: 20px;
|
|
179
|
+
p {
|
|
180
|
+
color: red !important;
|
|
181
|
+
}
|
|
182
|
+
`;
|
|
183
|
+
|
|
184
|
+
const ButtonWrapper = styled.div`
|
|
185
|
+
width: 80%;
|
|
186
|
+
margin: auto;
|
|
187
|
+
display: flex;
|
|
188
|
+
justify-content: space-around;
|
|
189
|
+
padding-top: 20px;
|
|
190
|
+
`;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
4
|
+
import LeftArrowClickIcon from '../PropertySelect/img/ui-arrows/arrow01-left-clicked.png';
|
|
5
|
+
import LeftArrowIcon from '../PropertySelect/img/ui-arrows/arrow01-left.png';
|
|
6
|
+
import RightArrowClickIcon from '../PropertySelect/img/ui-arrows/arrow01-right-clicked.png';
|
|
7
|
+
import RightArrowIcon from '../PropertySelect/img/ui-arrows/arrow01-right.png';
|
|
8
|
+
import { ITransactionItem } from '@rpg-engine/shared';
|
|
9
|
+
|
|
10
|
+
export interface ITradeComponentProps {
|
|
11
|
+
traderItem: ITransactionItem;
|
|
12
|
+
updateChartTotals: (traderItem: ITransactionItem) => void;
|
|
13
|
+
atlasJSON: any;
|
|
14
|
+
atlasIMG: any;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ItemTradingComponent: React.FC<ITradeComponentProps> = ({
|
|
18
|
+
atlasIMG,
|
|
19
|
+
atlasJSON,
|
|
20
|
+
updateChartTotals,
|
|
21
|
+
traderItem,
|
|
22
|
+
}) => {
|
|
23
|
+
const [itemQuantity, setItemQuantity] = useState(0);
|
|
24
|
+
|
|
25
|
+
const onLeftClick = () => {
|
|
26
|
+
if (itemQuantity > 0) {
|
|
27
|
+
const newQuantity = itemQuantity - 1;
|
|
28
|
+
setItemQuantity(newQuantity);
|
|
29
|
+
updateChartTotals({
|
|
30
|
+
key: traderItem.key,
|
|
31
|
+
itemId: traderItem.itemId,
|
|
32
|
+
qty: newQuantity,
|
|
33
|
+
price: traderItem.price,
|
|
34
|
+
texturePath: traderItem.texturePath,
|
|
35
|
+
name: traderItem.name,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const onRightClick = () => {
|
|
40
|
+
const newQuantity = itemQuantity + 1;
|
|
41
|
+
setItemQuantity(newQuantity);
|
|
42
|
+
updateChartTotals({
|
|
43
|
+
key: traderItem.key,
|
|
44
|
+
itemId: traderItem.itemId,
|
|
45
|
+
qty: newQuantity,
|
|
46
|
+
price: traderItem.price,
|
|
47
|
+
texturePath: traderItem.texturePath,
|
|
48
|
+
name: traderItem.name,
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<ItemWrapper>
|
|
54
|
+
<IconContainer>
|
|
55
|
+
<SpriteContainer>
|
|
56
|
+
<SpriteFromAtlas
|
|
57
|
+
atlasIMG={atlasIMG}
|
|
58
|
+
atlasJSON={atlasJSON}
|
|
59
|
+
spriteKey={traderItem.texturePath}
|
|
60
|
+
imgScale={2.5}
|
|
61
|
+
/>
|
|
62
|
+
</SpriteContainer>
|
|
63
|
+
</IconContainer>
|
|
64
|
+
<NameValue>
|
|
65
|
+
<p>{traderItem.name}</p>
|
|
66
|
+
<p>${traderItem.price}</p>
|
|
67
|
+
</NameValue>
|
|
68
|
+
<Container>
|
|
69
|
+
<TextOverlay>
|
|
70
|
+
<Item>{itemQuantity}</Item>
|
|
71
|
+
</TextOverlay>
|
|
72
|
+
<LeftArrow onClick={onLeftClick} onTouchStart={onLeftClick}></LeftArrow>
|
|
73
|
+
<RightArrow
|
|
74
|
+
onClick={onRightClick}
|
|
75
|
+
onTouchStart={onRightClick}
|
|
76
|
+
></RightArrow>
|
|
77
|
+
</Container>
|
|
78
|
+
</ItemWrapper>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const ItemWrapper = styled.div`
|
|
83
|
+
width: 80%;
|
|
84
|
+
margin: auto;
|
|
85
|
+
display: flex;
|
|
86
|
+
justify-content: space-between;
|
|
87
|
+
`;
|
|
88
|
+
|
|
89
|
+
const IconContainer = styled.div`
|
|
90
|
+
display: flex;
|
|
91
|
+
justify-content: center;
|
|
92
|
+
align-items: center;
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
const SpriteContainer = styled.div`
|
|
96
|
+
position: relative;
|
|
97
|
+
top: -3px;
|
|
98
|
+
left: 0;
|
|
99
|
+
`;
|
|
100
|
+
|
|
101
|
+
const NameValue = styled.div``;
|
|
102
|
+
|
|
103
|
+
const Item = styled.span`
|
|
104
|
+
font-size: 1rem;
|
|
105
|
+
color: white;
|
|
106
|
+
text-align: center;
|
|
107
|
+
z-index: 1;
|
|
108
|
+
position: absolute;
|
|
109
|
+
top: -12px;
|
|
110
|
+
width: 100%;
|
|
111
|
+
`;
|
|
112
|
+
|
|
113
|
+
const TextOverlay = styled.div`
|
|
114
|
+
width: 100%;
|
|
115
|
+
position: relative;
|
|
116
|
+
`;
|
|
117
|
+
|
|
118
|
+
interface IContainerProps {
|
|
119
|
+
percentageWidth?: number;
|
|
120
|
+
minWidth?: number;
|
|
121
|
+
style?: Record<string, any>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const Container = styled.div<IContainerProps>`
|
|
125
|
+
position: relative;
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-direction: column;
|
|
128
|
+
justify-content: space-around;
|
|
129
|
+
align-items: flex-start;
|
|
130
|
+
min-width: 100px;
|
|
131
|
+
width: 40%;
|
|
132
|
+
`;
|
|
133
|
+
|
|
134
|
+
const LeftArrow = styled.div`
|
|
135
|
+
background-image: url(${LeftArrowIcon});
|
|
136
|
+
background-size: 100% 100%;
|
|
137
|
+
left: 0;
|
|
138
|
+
position: absolute;
|
|
139
|
+
width: 40px;
|
|
140
|
+
height: 42px;
|
|
141
|
+
:active {
|
|
142
|
+
background-image: url(${LeftArrowClickIcon});
|
|
143
|
+
}
|
|
144
|
+
z-index: 2;
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
const RightArrow = styled.div`
|
|
148
|
+
background-image: url(${RightArrowIcon});
|
|
149
|
+
right: 0;
|
|
150
|
+
position: absolute;
|
|
151
|
+
width: 40px;
|
|
152
|
+
background-size: 100% 100%;
|
|
153
|
+
height: 42px;
|
|
154
|
+
:active {
|
|
155
|
+
background-image: url(${RightArrowClickIcon});
|
|
156
|
+
}
|
|
157
|
+
z-index: 2;
|
|
158
|
+
`;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { ITransactionItem } from '@rpg-engine/shared';
|
|
2
|
+
export const itemMock: ITransactionItem[] = [
|
|
3
|
+
{
|
|
4
|
+
texturePath: 'swords/broad-sword.png',
|
|
5
|
+
itemId: 'itemId01',
|
|
6
|
+
name: 'sword',
|
|
7
|
+
price: 100,
|
|
8
|
+
key: 'Short sword',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
texturePath: 'swords/broad-sword.png',
|
|
12
|
+
itemId: 'itemId02',
|
|
13
|
+
name: 'sword',
|
|
14
|
+
price: 100,
|
|
15
|
+
key: 'Short sword',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
texturePath: 'swords/broad-sword.png',
|
|
19
|
+
itemId: 'itemId03',
|
|
20
|
+
name: 'sword',
|
|
21
|
+
price: 100,
|
|
22
|
+
key: 'Short sword',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
texturePath: 'swords/broad-sword.png',
|
|
26
|
+
itemId: 'itemId01',
|
|
27
|
+
name: 'sword',
|
|
28
|
+
price: 100,
|
|
29
|
+
key: 'Short sword',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
texturePath: 'swords/broad-sword.png',
|
|
33
|
+
itemId: 'itemId02',
|
|
34
|
+
name: 'sword',
|
|
35
|
+
price: 100,
|
|
36
|
+
key: 'Short sword',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
texturePath: 'swords/broad-sword.png',
|
|
40
|
+
itemId: 'itemId03',
|
|
41
|
+
name: 'sword',
|
|
42
|
+
price: 100,
|
|
43
|
+
key: 'Short sword',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
texturePath: 'swords/broad-sword.png',
|
|
47
|
+
itemId: 'itemId01',
|
|
48
|
+
name: 'sword',
|
|
49
|
+
price: 100,
|
|
50
|
+
key: 'Short sword',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
texturePath: 'swords/broad-sword.png',
|
|
54
|
+
itemId: 'itemId02',
|
|
55
|
+
name: 'sword',
|
|
56
|
+
price: 100,
|
|
57
|
+
key: 'Short sword',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
texturePath: 'swords/broad-sword.png',
|
|
61
|
+
itemId: 'itemId03',
|
|
62
|
+
name: 'sword',
|
|
63
|
+
price: 100,
|
|
64
|
+
key: 'Short sword',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
texturePath: 'swords/broad-sword.png',
|
|
68
|
+
itemId: 'itemId01',
|
|
69
|
+
name: 'sword',
|
|
70
|
+
price: 100,
|
|
71
|
+
key: 'Short sword',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
texturePath: 'swords/broad-sword.png',
|
|
75
|
+
itemId: 'itemId02',
|
|
76
|
+
name: 'sword',
|
|
77
|
+
price: 100,
|
|
78
|
+
key: 'Short sword',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
texturePath: 'swords/broad-sword.png',
|
|
82
|
+
itemId: 'itemId03',
|
|
83
|
+
name: 'sword',
|
|
84
|
+
price: 100,
|
|
85
|
+
key: 'Short sword',
|
|
86
|
+
},
|
|
87
|
+
];
|
package/src/index.tsx
CHANGED
|
@@ -27,4 +27,5 @@ export * from './components/Truncate';
|
|
|
27
27
|
export * from './components/typography/DynamicText';
|
|
28
28
|
export * from './components/NPCDialog/NPCMultiDialog';
|
|
29
29
|
export * from './components/HistoryDialog';
|
|
30
|
+
export * from './components/TradingMenu/TrandingMenu';
|
|
30
31
|
export { useEventListener } from './hooks/useEventListener';
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Meta, Story } from '@storybook/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { RPGUIRoot } from '../components/RPGUIRoot';
|
|
4
|
+
import {
|
|
5
|
+
ItemTradingComponent,
|
|
6
|
+
ITradeComponentProps,
|
|
7
|
+
} from '../components/TradingMenu/itemComponent';
|
|
8
|
+
import atlasJSON from '../mocks/atlas/items/items.json';
|
|
9
|
+
import atlasIMG from '../mocks/atlas/items/items.png';
|
|
10
|
+
import { itemMock } from '../components/TradingMenu/items.mock';
|
|
11
|
+
import { ITransactionItem } from '@rpg-engine/shared';
|
|
12
|
+
|
|
13
|
+
const updateChartTotals = (itemInfo: ITransactionItem) => {
|
|
14
|
+
console.log(itemInfo);
|
|
15
|
+
// will be needed read all itens from chart list ignoring the current item (itemInfo) and recalculate the totals
|
|
16
|
+
// with the amount updated set the total to a state to be shown to the player.
|
|
17
|
+
// OBS: This list with Id, quantity and amount will be the one to send to API,
|
|
18
|
+
// because the API need to know wichi Items and the quantity of it to make a purchese and set the itens to the player.
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const meta: Meta = {
|
|
22
|
+
title: 'Trading Item',
|
|
23
|
+
component: ItemTradingComponent,
|
|
24
|
+
};
|
|
25
|
+
export default meta;
|
|
26
|
+
|
|
27
|
+
const Template: Story<ITradeComponentProps> = args => (
|
|
28
|
+
<RPGUIRoot>
|
|
29
|
+
<ItemTradingComponent {...args} traderItem={itemMock[0]} />
|
|
30
|
+
</RPGUIRoot>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export const Default = Template.bind({});
|
|
34
|
+
|
|
35
|
+
Default.args = {
|
|
36
|
+
atlasIMG: atlasIMG,
|
|
37
|
+
atlasJSON: atlasJSON,
|
|
38
|
+
updateChartTotals,
|
|
39
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Meta, Story } from '@storybook/react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { RPGUIRoot } from '../../src/components/RPGUIRoot';
|
|
4
|
+
import atlasJSON from '../mocks/atlas/items/items.json';
|
|
5
|
+
import atlasIMG from '../mocks/atlas/items/items.png';
|
|
4
6
|
import {
|
|
5
7
|
ISkillProgressBarProps,
|
|
6
8
|
SkillProgressBar,
|
|
@@ -27,4 +29,6 @@ Default.args = {
|
|
|
27
29
|
skillPoints: 10,
|
|
28
30
|
skillPointsToNextLevel: 100,
|
|
29
31
|
texturePath: 'swords/broad-sword.png',
|
|
32
|
+
atlasIMG: atlasIMG,
|
|
33
|
+
atlasJSON: atlasJSON,
|
|
30
34
|
};
|