@rpg-engine/long-bow 0.4.7 → 0.4.9

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.
Files changed (177) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +181 -181
  3. package/dist/components/ConfirmModal.d.ts +8 -0
  4. package/dist/components/DraggableContainer.d.ts +1 -0
  5. package/dist/components/Item/Inventory/ItemSlot.d.ts +7 -7
  6. package/dist/components/Marketplace/BuyPanel.d.ts +23 -0
  7. package/dist/components/Marketplace/ManagmentPanel.d.ts +19 -0
  8. package/dist/components/Marketplace/Marketplace.d.ts +22 -9
  9. package/dist/components/Marketplace/MarketplaceRows.d.ts +3 -1
  10. package/dist/components/Marketplace/{__mocks__ → filters}/index.d.ts +1 -3
  11. package/dist/components/Pager.d.ts +9 -0
  12. package/dist/long-bow.cjs.development.js +1573 -1163
  13. package/dist/long-bow.cjs.development.js.map +1 -1
  14. package/dist/long-bow.cjs.production.min.js +1 -1
  15. package/dist/long-bow.cjs.production.min.js.map +1 -1
  16. package/dist/long-bow.esm.js +1629 -1219
  17. package/dist/long-bow.esm.js.map +1 -1
  18. package/package.json +100 -100
  19. package/src/components/Abstractions/ModalPortal.tsx +22 -22
  20. package/src/components/Abstractions/SlotsContainer.tsx +62 -62
  21. package/src/components/Arrow/SelectArrow.tsx +69 -69
  22. package/src/components/Arrow/img/arrow01-left-clicked.png +0 -0
  23. package/src/components/Arrow/img/arrow01-left.png +0 -0
  24. package/src/components/Arrow/img/arrow01-right-clicked.png +0 -0
  25. package/src/components/Arrow/img/arrow01-right.png +0 -0
  26. package/src/components/Arrow/img/arrow02-left-clicked.png +0 -0
  27. package/src/components/Arrow/img/arrow02-left.png +0 -0
  28. package/src/components/Arrow/img/arrow02-right-clicked.png +0 -0
  29. package/src/components/Arrow/img/arrow02-right.png +0 -0
  30. package/src/components/Button.tsx +40 -40
  31. package/src/components/Character/CharacterSelection.tsx +98 -98
  32. package/src/components/CharacterStatus/CharacterStatus.tsx +120 -120
  33. package/src/components/Chat/Chat.tsx +196 -196
  34. package/src/components/Chatdeprecated/ChatDeprecated.tsx +198 -198
  35. package/src/components/CheckButton.tsx +65 -65
  36. package/src/components/CircularController/CircularController.tsx +282 -282
  37. package/src/components/ConfirmModal.tsx +87 -0
  38. package/src/components/CraftBook/CraftBook.tsx +286 -286
  39. package/src/components/CraftBook/CraftingRecipe.tsx +161 -161
  40. package/src/components/CraftBook/MockItems.ts +101 -101
  41. package/src/components/DraggableContainer.tsx +183 -180
  42. package/src/components/Dropdown.tsx +114 -106
  43. package/src/components/DropdownSelectorContainer.tsx +42 -42
  44. package/src/components/Equipment/EquipmentSet.tsx +199 -199
  45. package/src/components/HistoryDialog.tsx +104 -104
  46. package/src/components/Input.tsx +15 -15
  47. package/src/components/InputRadio.tsx +41 -41
  48. package/src/components/Item/Cards/ItemInfo.tsx +298 -298
  49. package/src/components/Item/Cards/ItemInfoDisplay.tsx +135 -135
  50. package/src/components/Item/Cards/ItemInfoWrapper.tsx +62 -62
  51. package/src/components/Item/Cards/ItemTooltip.tsx +83 -83
  52. package/src/components/Item/Cards/MobileItemTooltip.tsx +149 -149
  53. package/src/components/Item/Inventory/ErrorBoundary.tsx +42 -42
  54. package/src/components/Item/Inventory/ItemContainer.tsx +231 -231
  55. package/src/components/Item/Inventory/ItemContainerTypes.ts +6 -6
  56. package/src/components/Item/Inventory/ItemQuantitySelector.tsx +138 -138
  57. package/src/components/Item/Inventory/ItemSlot.tsx +595 -580
  58. package/src/components/Item/Inventory/itemContainerHelper.ts +175 -175
  59. package/src/components/ListMenu.tsx +63 -63
  60. package/src/components/Marketplace/BuyPanel.tsx +304 -0
  61. package/src/components/Marketplace/ManagmentPanel.tsx +255 -0
  62. package/src/components/Marketplace/Marketplace.tsx +106 -132
  63. package/src/components/Marketplace/MarketplaceRows.tsx +177 -171
  64. package/src/components/Marketplace/{__mocks__ → filters}/index.tsx +67 -65
  65. package/src/components/Multitab/Tab.tsx +66 -66
  66. package/src/components/Multitab/TabBody.tsx +13 -13
  67. package/src/components/Multitab/TabsContainer.tsx +97 -97
  68. package/src/components/NPCDialog/NPCDialog.tsx +121 -121
  69. package/src/components/NPCDialog/NPCDialogText.tsx +113 -113
  70. package/src/components/NPCDialog/NPCMultiDialog.tsx +159 -159
  71. package/src/components/NPCDialog/QuestionDialog/QuestionDialog.tsx +237 -237
  72. package/src/components/Pager.tsx +94 -0
  73. package/src/components/ProgressBar.tsx +95 -95
  74. package/src/components/PropertySelect/PropertySelect.tsx +106 -106
  75. package/src/components/QuestInfo/QuestInfo.tsx +233 -233
  76. package/src/components/QuestList.tsx +135 -135
  77. package/src/components/RPGUIContainer.tsx +47 -47
  78. package/src/components/RPGUIForceRenderStart.tsx +45 -45
  79. package/src/components/RPGUIRoot.tsx +14 -14
  80. package/src/components/RadioButton.tsx +53 -53
  81. package/src/components/RadioInput/RadioButton.tsx +96 -96
  82. package/src/components/RadioInput/RadioInput.tsx +102 -102
  83. package/src/components/RadioInput/instruments.ts +15 -15
  84. package/src/components/RangeSlider.tsx +78 -78
  85. package/src/components/RelativeListMenu.tsx +90 -90
  86. package/src/components/ScrollList.tsx +79 -79
  87. package/src/components/Shortcuts/Shortcuts.tsx +193 -193
  88. package/src/components/Shortcuts/ShortcutsSetter.tsx +139 -139
  89. package/src/components/Shortcuts/SingleShortcut.ts +82 -82
  90. package/src/components/Shortcuts/useShortcutCooldown.ts +23 -23
  91. package/src/components/SimpleProgressBar.tsx +62 -62
  92. package/src/components/SkillProgressBar.tsx +198 -198
  93. package/src/components/SkillsContainer.tsx +213 -213
  94. package/src/components/Spellbook/Spell.tsx +235 -236
  95. package/src/components/Spellbook/Spellbook.tsx +145 -161
  96. package/src/components/Spellbook/cards/MobileSpellTooltip.tsx +137 -137
  97. package/src/components/Spellbook/cards/SpellInfo.tsx +134 -134
  98. package/src/components/Spellbook/cards/SpellInfoDisplay.tsx +31 -31
  99. package/src/components/Spellbook/cards/SpellInfoWrapper.tsx +48 -48
  100. package/src/components/Spellbook/cards/SpellTooltip.tsx +70 -70
  101. package/src/components/Spellbook/constants.ts +7 -7
  102. package/src/components/Spellbook/mockSpells.ts +84 -84
  103. package/src/components/StaticBook/StaticBook.tsx +103 -103
  104. package/src/components/TextArea.tsx +11 -11
  105. package/src/components/TimeWidget/DayNightPeriod/DayNightPeriod.tsx +35 -35
  106. package/src/components/TimeWidget/TimeWidget.tsx +65 -65
  107. package/src/components/TradingMenu/TradingItemRow.tsx +199 -199
  108. package/src/components/TradingMenu/TradingMenu.tsx +219 -219
  109. package/src/components/TradingMenu/items.mock.ts +48 -48
  110. package/src/components/Truncate.tsx +25 -25
  111. package/src/components/itemSelector/ItemSelector.tsx +136 -136
  112. package/src/components/shared/Column.tsx +16 -16
  113. package/src/components/shared/Ellipsis.tsx +76 -68
  114. package/src/components/shared/SpriteFromAtlas.tsx +104 -104
  115. package/src/components/typography/DynamicText.tsx +49 -49
  116. package/src/constants/uiColors.ts +20 -20
  117. package/src/constants/uiDevices.ts +3 -3
  118. package/src/constants/uiFonts.ts +12 -12
  119. package/src/hooks/useEventListener.ts +21 -21
  120. package/src/hooks/useOutsideAlerter.ts +25 -25
  121. package/src/index.tsx +42 -42
  122. package/src/libs/CastingTypeHelper.ts +7 -7
  123. package/src/libs/StringHelpers.ts +3 -3
  124. package/src/libs/itemCounter.ts +21 -21
  125. package/src/mocks/atlas/entities/entities.json +20215 -20215
  126. package/src/mocks/atlas/icons/icons.json +735 -735
  127. package/src/mocks/atlas/items/items.json +12086 -12086
  128. package/src/mocks/equipmentSet.mocks.ts +391 -391
  129. package/src/mocks/itemContainer.mocks.ts +605 -605
  130. package/src/mocks/skills.mocks.ts +130 -130
  131. package/src/stories/Arrow.stories.tsx +26 -26
  132. package/src/stories/Button.stories.tsx +36 -36
  133. package/src/stories/CharacterSelection.stories.tsx +44 -44
  134. package/src/stories/CharacterStatus.stories.tsx +29 -29
  135. package/src/stories/Chat.stories.tsx +187 -187
  136. package/src/stories/ChatDeprecated.stories.tsx +170 -170
  137. package/src/stories/CheckButton.stories.tsx +48 -48
  138. package/src/stories/CircullarController.stories.tsx +37 -37
  139. package/src/stories/CraftBook.stories.tsx +42 -42
  140. package/src/stories/DayNightPeriod.stories.tsx +27 -27
  141. package/src/stories/DraggableContainer.stories.tsx +28 -28
  142. package/src/stories/Dropdown.stories.tsx +46 -46
  143. package/src/stories/DropdownSelectorContainer.stories.tsx +41 -41
  144. package/src/stories/EquipmentSet.stories.tsx +65 -65
  145. package/src/stories/HistoryDialog.stories.tsx +61 -61
  146. package/src/stories/ItemContainer.stories.tsx +201 -201
  147. package/src/stories/ItemInfoDisplay.stories.tsx +33 -33
  148. package/src/stories/ItemQuantitySelector.stories.tsx +26 -26
  149. package/src/stories/ItemSelector.stories.tsx +77 -77
  150. package/src/stories/ItemTradingComponent.stories.tsx +35 -35
  151. package/src/stories/ListMenu.stories.tsx +56 -56
  152. package/src/stories/Marketplace.stories.tsx +57 -42
  153. package/src/stories/MarketplaceRows.stories.tsx +27 -28
  154. package/src/stories/Multitab.stories.tsx +51 -51
  155. package/src/stories/NPCDialog.stories.tsx +130 -130
  156. package/src/stories/NPCMultiDialog.stories.tsx +71 -71
  157. package/src/stories/ProgressBar.stories.tsx +23 -23
  158. package/src/stories/PropertySelect.stories.tsx +40 -40
  159. package/src/stories/QuestInfo.stories.tsx +107 -107
  160. package/src/stories/QuestList.stories.tsx +82 -82
  161. package/src/stories/RPGUIContainers.stories.tsx +42 -42
  162. package/src/stories/RadioButton.stories.tsx +49 -49
  163. package/src/stories/RadioInput.stories.tsx +34 -34
  164. package/src/stories/RangeSlider.stories.tsx +64 -64
  165. package/src/stories/ScrollList.stories.tsx +85 -85
  166. package/src/stories/Shortcuts.stories.tsx +39 -39
  167. package/src/stories/SimpleProgressBar.stories.tsx +22 -22
  168. package/src/stories/SkillProgressBar.stories.tsx +34 -34
  169. package/src/stories/SkillsContainer.stories.tsx +35 -35
  170. package/src/stories/SpellInfoDisplay.stories.tsx +27 -27
  171. package/src/stories/Spellbook.stories.tsx +104 -104
  172. package/src/stories/StaticBook.stories.tsx +32 -32
  173. package/src/stories/Text.stories.tsx +42 -42
  174. package/src/stories/TimeWidget.stories.tsx +27 -27
  175. package/src/stories/TradingMenu.stories.tsx +47 -47
  176. package/src/types/eventTypes.ts +4 -4
  177. package/src/types/index.d.ts +2 -2
@@ -0,0 +1,304 @@
1
+ import { IEquipmentSet, IMarketplaceItem } from '@rpg-engine/shared';
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import { AiFillCaretRight } from 'react-icons/ai';
4
+ import styled from 'styled-components';
5
+ import { ConfirmModal } from '../ConfirmModal';
6
+ import { Dropdown } from '../Dropdown';
7
+ import { Input } from '../Input';
8
+ import { MarketplaceRows } from './MarketplaceRows';
9
+ import { itemRarityOptions, itemTypeOptions, orderByOptions } from './filters';
10
+
11
+ export interface IBuyPanelProps {
12
+ items: IMarketplaceItem[];
13
+ atlasJSON: any;
14
+ atlasIMG: any;
15
+ onClose: () => void;
16
+ onChangeType: (value: string) => void;
17
+ onChangeRarity: (value: string) => void;
18
+ onChangeOrder: (value: string) => void;
19
+ onChangeNameInput: (value: string) => void;
20
+ onChangeMainLevelInput: (
21
+ value: [number | undefined, number | undefined]
22
+ ) => void;
23
+ onChangeSecondaryLevelInput: (
24
+ value: [number | undefined, number | undefined]
25
+ ) => void;
26
+ onChangePriceInput: (value: [number | undefined, number | undefined]) => void;
27
+ scale?: number;
28
+ equipmentSet?: IEquipmentSet | null;
29
+ onMarketPlaceItemBuy?: (marketPlaceItemId: string) => void;
30
+ characterId: string;
31
+ enableHotkeys?: () => void;
32
+ disableHotkeys?: () => void;
33
+ currentPage: number;
34
+ }
35
+
36
+ export const BuyPanel: React.FC<IBuyPanelProps> = ({
37
+ items,
38
+ atlasIMG,
39
+ atlasJSON,
40
+ onChangeType,
41
+ onChangeRarity,
42
+ onChangeOrder,
43
+ onChangeNameInput,
44
+ onChangeMainLevelInput,
45
+ onChangeSecondaryLevelInput,
46
+ onChangePriceInput,
47
+ equipmentSet,
48
+ onMarketPlaceItemBuy,
49
+ characterId,
50
+ enableHotkeys,
51
+ disableHotkeys,
52
+ currentPage,
53
+ }) => {
54
+ const [name, setName] = useState('');
55
+ const [mainLevel, setMainLevel] = useState<
56
+ [number | undefined, number | undefined]
57
+ >([undefined, undefined]);
58
+ const [secondaryLevel, setSecondaryLevel] = useState<
59
+ [number | undefined, number | undefined]
60
+ >([undefined, undefined]);
61
+ const [price, setPrice] = useState<[number | undefined, number | undefined]>([
62
+ undefined,
63
+ undefined,
64
+ ]);
65
+ const [buyingItemId, setBuyingItemId] = useState<string | null>(null);
66
+
67
+ const itemsContainer = useRef<HTMLDivElement>(null);
68
+
69
+ useEffect(() => {
70
+ itemsContainer.current?.scrollTo(0, 0);
71
+ }, [currentPage]);
72
+
73
+ return (
74
+ <>
75
+ {buyingItemId && (
76
+ <ConfirmModal
77
+ onClose={setBuyingItemId.bind(null, null)}
78
+ onConfirm={() => {
79
+ onMarketPlaceItemBuy?.(buyingItemId);
80
+ setBuyingItemId(null);
81
+ enableHotkeys?.();
82
+ }}
83
+ message="Are you sure to buy this item?"
84
+ />
85
+ )}
86
+ <InputWrapper>
87
+ <p>Search By Name</p>
88
+ <Input
89
+ onChange={e => {
90
+ setName(e.target.value);
91
+ onChangeNameInput(e.target.value);
92
+ }}
93
+ value={name}
94
+ placeholder="Enter name..."
95
+ onBlur={enableHotkeys}
96
+ onFocus={disableHotkeys}
97
+ />
98
+ </InputWrapper>
99
+
100
+ <OptionsWrapper>
101
+ <FilterInputsWrapper>
102
+ <div>
103
+ <p>Main level</p>
104
+ <Input
105
+ onChange={e => {
106
+ setMainLevel([Number(e.target.value), mainLevel[1]]);
107
+ onChangeMainLevelInput([Number(e.target.value), mainLevel[1]]);
108
+ }}
109
+ placeholder="Min"
110
+ type="number"
111
+ min={0}
112
+ onBlur={enableHotkeys}
113
+ onFocus={disableHotkeys}
114
+ />
115
+ <AiFillCaretRight />
116
+ <Input
117
+ onChange={e => {
118
+ setMainLevel([mainLevel[0], Number(e.target.value)]);
119
+ onChangeMainLevelInput([mainLevel[0], Number(e.target.value)]);
120
+ }}
121
+ placeholder="Max"
122
+ type="number"
123
+ min={0}
124
+ onBlur={enableHotkeys}
125
+ onFocus={disableHotkeys}
126
+ />
127
+ </div>
128
+
129
+ <div>
130
+ <p>Secondary level</p>
131
+ <Input
132
+ onChange={e => {
133
+ setSecondaryLevel([Number(e.target.value), secondaryLevel[1]]);
134
+ onChangeSecondaryLevelInput([
135
+ Number(e.target.value),
136
+ secondaryLevel[1],
137
+ ]);
138
+ }}
139
+ placeholder="Min"
140
+ type="number"
141
+ min={0}
142
+ onBlur={enableHotkeys}
143
+ onFocus={disableHotkeys}
144
+ />
145
+ <AiFillCaretRight />
146
+ <Input
147
+ onChange={e => {
148
+ setSecondaryLevel([secondaryLevel[0], Number(e.target.value)]);
149
+ onChangeSecondaryLevelInput([
150
+ secondaryLevel[0],
151
+ Number(e.target.value),
152
+ ]);
153
+ }}
154
+ placeholder="Max"
155
+ type="number"
156
+ min={0}
157
+ onBlur={enableHotkeys}
158
+ onFocus={disableHotkeys}
159
+ />
160
+ </div>
161
+
162
+ <div>
163
+ <p>Price</p>
164
+ <Input
165
+ onChange={e => {
166
+ setPrice([Number(e.target.value), price[1]]);
167
+ onChangePriceInput([Number(e.target.value), price[1]]);
168
+ }}
169
+ placeholder="Min"
170
+ type="number"
171
+ min={0}
172
+ className="big-input"
173
+ onBlur={enableHotkeys}
174
+ onFocus={disableHotkeys}
175
+ />
176
+ <AiFillCaretRight />
177
+ <Input
178
+ onChange={e => {
179
+ setPrice([price[0], Number(e.target.value)]);
180
+ onChangePriceInput([price[0], Number(e.target.value)]);
181
+ }}
182
+ placeholder="Max"
183
+ type="number"
184
+ min={0}
185
+ className="big-input"
186
+ onBlur={enableHotkeys}
187
+ onFocus={disableHotkeys}
188
+ />
189
+ </div>
190
+ </FilterInputsWrapper>
191
+
192
+ <WrapperContainer>
193
+ <StyledDropdown
194
+ options={itemTypeOptions}
195
+ onChange={onChangeType}
196
+ width="95%"
197
+ />
198
+ <StyledDropdown
199
+ options={itemRarityOptions}
200
+ onChange={onChangeRarity}
201
+ width="95%"
202
+ />
203
+ <StyledDropdown
204
+ options={orderByOptions}
205
+ onChange={onChangeOrder}
206
+ width="100%"
207
+ />
208
+ </WrapperContainer>
209
+ </OptionsWrapper>
210
+
211
+ <ItemComponentScrollWrapper id="MarketContainer" ref={itemsContainer}>
212
+ {items?.map(({ item, price, _id, owner }, index) => (
213
+ <MarketplaceRows
214
+ key={`${item.key}_${index}`}
215
+ atlasIMG={atlasIMG}
216
+ atlasJSON={atlasJSON}
217
+ item={item}
218
+ itemPrice={price}
219
+ equipmentSet={equipmentSet}
220
+ onMarketPlaceItemBuy={setBuyingItemId.bind(null, _id)}
221
+ disabled={owner === characterId}
222
+ />
223
+ ))}
224
+ </ItemComponentScrollWrapper>
225
+ </>
226
+ );
227
+ };
228
+
229
+ const InputWrapper = styled.div`
230
+ width: 95%;
231
+ display: flex !important;
232
+ justify-content: flex-start;
233
+ align-items: center;
234
+ margin: auto;
235
+
236
+ p {
237
+ width: auto;
238
+ margin-right: 20px;
239
+ }
240
+
241
+ input {
242
+ width: 68%;
243
+ height: 10px;
244
+ }
245
+ `;
246
+
247
+ const OptionsWrapper = styled.div`
248
+ width: 100%;
249
+ height: 100px;
250
+ `;
251
+
252
+ const FilterInputsWrapper = styled.div`
253
+ width: 95%;
254
+ display: flex;
255
+ justify-content: space-between;
256
+ align-items: center;
257
+ margin-bottom: 10px;
258
+ margin-left: 10px;
259
+ gap: 5px;
260
+ color: white;
261
+ flex-wrap: wrap;
262
+
263
+ p {
264
+ width: auto;
265
+ margin: 0;
266
+ }
267
+
268
+ input {
269
+ width: 75px;
270
+ height: 10px;
271
+ }
272
+
273
+ .big-input {
274
+ width: 130px;
275
+ }
276
+ `;
277
+
278
+ const WrapperContainer = styled.div`
279
+ display: grid;
280
+ grid-template-columns: 40% 30% 30%;
281
+ justify-content: space-between;
282
+ width: calc(100% - 40px);
283
+ margin-left: 10px;
284
+
285
+ .rpgui-content .rpgui-dropdown-imp-header {
286
+ padding: 0px 10px 0 !important;
287
+ }
288
+ `;
289
+
290
+ const ItemComponentScrollWrapper = styled.div`
291
+ overflow-y: scroll;
292
+ height: 390px;
293
+ width: 100%;
294
+ margin-top: 1rem;
295
+
296
+ @media (max-width: 950px) {
297
+ height: 250px;
298
+ }
299
+ `;
300
+
301
+ const StyledDropdown = styled(Dropdown)`
302
+ margin: 3px !important;
303
+ width: 170px !important;
304
+ `;
@@ -0,0 +1,255 @@
1
+ import { IEquipmentSet, IItem, IMarketplaceItem } from '@rpg-engine/shared';
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import styled from 'styled-components';
4
+ import { uiColors } from '../../constants/uiColors';
5
+ import { uiFonts } from '../../constants/uiFonts';
6
+ import { Button, ButtonTypes } from '../Button';
7
+ import { ConfirmModal } from '../ConfirmModal';
8
+ import { Input } from '../Input';
9
+ import { ItemSlot } from '../Item/Inventory/ItemSlot';
10
+ import { MarketplaceRows } from './MarketplaceRows';
11
+
12
+ export interface IManagmentPanelProps {
13
+ items: IMarketplaceItem[];
14
+ atlasJSON: any;
15
+ atlasIMG: any;
16
+ onChangeNameInput: (value: string) => void;
17
+ equipmentSet?: IEquipmentSet | null;
18
+ availableGold: number;
19
+ onMarketPlaceItemRemove?: (marketPlaceItemId: string) => void;
20
+ selectedItemToSell: IItem | null;
21
+ onSelectedItemToSellRemove: (item: IItem) => void;
22
+ onAddItemToMarketplace: (item: IItem, price: number) => void;
23
+ enableHotkeys?: () => void;
24
+ disableHotkeys?: () => void;
25
+ onMoneyWithdraw: () => void;
26
+ currentPage: number;
27
+ }
28
+
29
+ export const ManagmentPanel: React.FC<IManagmentPanelProps> = ({
30
+ items,
31
+ atlasIMG,
32
+ atlasJSON,
33
+ onChangeNameInput,
34
+ equipmentSet,
35
+ availableGold,
36
+ onMarketPlaceItemRemove,
37
+ selectedItemToSell,
38
+ onSelectedItemToSellRemove,
39
+ onAddItemToMarketplace,
40
+ enableHotkeys,
41
+ disableHotkeys,
42
+ onMoneyWithdraw,
43
+ currentPage,
44
+ }) => {
45
+ const [name, setName] = useState('');
46
+ const [price, setPrice] = useState('');
47
+ const [isCreatingOffer, setIsCreatingOffer] = useState(false);
48
+ const [removingItemId, setRemovingItemId] = useState<string | null>(null);
49
+
50
+ const itemsContainer = useRef<HTMLDivElement>(null);
51
+
52
+ useEffect(() => {
53
+ itemsContainer.current?.scrollTo(0, 0);
54
+ }, [currentPage]);
55
+
56
+ return (
57
+ <>
58
+ {isCreatingOffer && (
59
+ <ConfirmModal
60
+ onClose={setIsCreatingOffer.bind(null, false)}
61
+ onConfirm={() => {
62
+ if (selectedItemToSell && price && Number(price)) {
63
+ onAddItemToMarketplace(selectedItemToSell, Number(price));
64
+ setPrice('');
65
+ onSelectedItemToSellRemove(selectedItemToSell);
66
+ setIsCreatingOffer(false);
67
+ enableHotkeys?.();
68
+ }
69
+ }}
70
+ message="Are you sure to create this offer?"
71
+ />
72
+ )}
73
+ {removingItemId && (
74
+ <ConfirmModal
75
+ onClose={setRemovingItemId.bind(null, null)}
76
+ onConfirm={() => {
77
+ onMarketPlaceItemRemove?.(removingItemId);
78
+ setRemovingItemId(null);
79
+ enableHotkeys?.();
80
+ }}
81
+ message="Are you sure to remove this item?"
82
+ />
83
+ )}
84
+ <InputWrapper>
85
+ <p>Search By Name</p>
86
+ <Input
87
+ onChange={e => {
88
+ setName(e.target.value);
89
+ onChangeNameInput(e.target.value);
90
+ }}
91
+ value={name}
92
+ placeholder="Enter name..."
93
+ onBlur={enableHotkeys}
94
+ onFocus={disableHotkeys}
95
+ />
96
+ </InputWrapper>
97
+
98
+ <OptionsWrapper>
99
+ <InnerOptionsWrapper>
100
+ <SellDescription>
101
+ Click on item in inventory to sell it
102
+ </SellDescription>
103
+ <Flex>
104
+ <ItemSlot
105
+ slotIndex={0}
106
+ atlasIMG={atlasIMG}
107
+ atlasJSON={atlasJSON}
108
+ onPointerDown={(_, __, item) => onSelectedItemToSellRemove(item)}
109
+ item={selectedItemToSell}
110
+ />
111
+ <PriceInputWrapper>
112
+ <p>Enter price</p>
113
+ <Flex>
114
+ <Input
115
+ onChange={e => {
116
+ setPrice(e.target.value);
117
+ }}
118
+ value={price}
119
+ placeholder="Enter price..."
120
+ type="number"
121
+ disabled={!selectedItemToSell}
122
+ onBlur={enableHotkeys}
123
+ onFocus={disableHotkeys}
124
+ />
125
+ <Button
126
+ buttonType={ButtonTypes.RPGUIButton}
127
+ disabled={!selectedItemToSell || !price}
128
+ onPointerDown={() => {
129
+ if (selectedItemToSell && price && Number(price)) {
130
+ setIsCreatingOffer(true);
131
+ }
132
+ }}
133
+ >
134
+ Create offer
135
+ </Button>
136
+ </Flex>
137
+ </PriceInputWrapper>
138
+ </Flex>
139
+ </InnerOptionsWrapper>
140
+ <InnerOptionsWrapper>
141
+ <AvailableGold $disabled={availableGold === 0}>
142
+ <p>Available gold</p>
143
+ <p className="center">${availableGold}</p>
144
+ <Button
145
+ buttonType={ButtonTypes.RPGUIButton}
146
+ disabled={availableGold === 0}
147
+ onPointerDown={() => availableGold > 0 && onMoneyWithdraw()}
148
+ >
149
+ Withdraw
150
+ </Button>
151
+ </AvailableGold>
152
+ </InnerOptionsWrapper>
153
+ </OptionsWrapper>
154
+
155
+ <ItemComponentScrollWrapper id="MarketContainer" ref={itemsContainer}>
156
+ {items?.map(({ item, price, _id }, index) => (
157
+ <MarketplaceRows
158
+ key={`${item.key}_${index}`}
159
+ atlasIMG={atlasIMG}
160
+ atlasJSON={atlasJSON}
161
+ item={item}
162
+ itemPrice={price}
163
+ equipmentSet={equipmentSet}
164
+ onMarketPlaceItemRemove={setRemovingItemId.bind(null, _id)}
165
+ />
166
+ ))}
167
+ </ItemComponentScrollWrapper>
168
+ </>
169
+ );
170
+ };
171
+
172
+ const Flex = styled.div`
173
+ display: flex;
174
+ gap: 5px;
175
+ align-items: center;
176
+ `;
177
+
178
+ const InputWrapper = styled.div`
179
+ width: 95%;
180
+ display: flex !important;
181
+ justify-content: flex-start;
182
+ align-items: center;
183
+ margin: auto;
184
+
185
+ p {
186
+ width: auto;
187
+ margin-right: 20px;
188
+ }
189
+
190
+ input {
191
+ width: 68%;
192
+ height: 10px;
193
+ }
194
+ `;
195
+
196
+ const OptionsWrapper = styled.div`
197
+ width: 100%;
198
+ height: 100px;
199
+ display: flex;
200
+ align-items: center;
201
+ justify-content: space-around;
202
+ `;
203
+
204
+ const InnerOptionsWrapper = styled.div`
205
+ display: flex;
206
+ justify-content: space-between;
207
+ flex-direction: column;
208
+ height: 100%;
209
+ `;
210
+
211
+ const ItemComponentScrollWrapper = styled.div`
212
+ overflow-y: scroll;
213
+ height: 390px;
214
+ width: 100%;
215
+ margin-top: 1rem;
216
+
217
+ @media (max-width: 950px) {
218
+ height: 250px;
219
+ }
220
+ `;
221
+
222
+ const PriceInputWrapper = styled.div`
223
+ p {
224
+ margin: 0;
225
+ }
226
+
227
+ input {
228
+ width: 200px;
229
+ }
230
+ `;
231
+
232
+ const SellDescription = styled.p`
233
+ margin: 0;
234
+ font-size: ${uiFonts.size.xsmall} !important;
235
+ `;
236
+
237
+ const AvailableGold = styled.div<{ $disabled: boolean }>`
238
+ height: 100%;
239
+ display: flex;
240
+ flex-direction: column;
241
+ justify-content: space-between;
242
+
243
+ p {
244
+ margin: 0;
245
+ color: ${props =>
246
+ props.$disabled ? uiColors.lightGray : 'white'} !important;
247
+ }
248
+
249
+ .center {
250
+ text-align: center;
251
+ font-size: ${uiFonts.size.large} !important;
252
+ color: ${props =>
253
+ props.$disabled ? uiColors.lightGray : uiColors.lightGreen} !important;
254
+ }
255
+ `;