@rpg-engine/long-bow 0.8.74 → 0.8.75

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.74",
3
+ "version": "0.8.75",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -5,7 +5,7 @@ import {
5
5
  TaskType,
6
6
  } from '@rpg-engine/shared';
7
7
  import React from 'react';
8
- import styled, { keyframes, css } from 'styled-components';
8
+ import styled, { css, keyframes } from 'styled-components';
9
9
  import { uiColors } from '../../constants/uiColors';
10
10
  import { Button, ButtonTypes } from '../Button';
11
11
  import { Ellipsis } from '../shared/Ellipsis';
@@ -36,6 +36,7 @@ export const DailyTaskItem: React.FC<IDailyTaskItemProps> = ({
36
36
  iconAtlasJSON,
37
37
  iconAtlasIMG,
38
38
  isRewardClaimed,
39
+ isPinned,
39
40
  }) => {
40
41
  const isMobile = isMobileOrTablet();
41
42
 
@@ -43,19 +44,22 @@ export const DailyTaskItem: React.FC<IDailyTaskItemProps> = ({
43
44
  const isInProgress = task.status === TaskStatus.InProgress;
44
45
  const isNotStarted = task.status === TaskStatus.NotStarted;
45
46
  const isClaimed = task.claimed || isRewardClaimed;
47
+ const isChallenge = task.difficulty?.toLowerCase() === 'challenge';
46
48
 
47
49
  const handleClaimReward = () => {
48
50
  onClaimReward(task.key, task.type);
49
51
  };
50
52
 
51
53
  return (
52
- <TaskContainer
54
+ <TaskContainer
53
55
  isMobile={isMobile}
54
56
  isCompleted={isCompleted}
55
57
  isInProgress={isInProgress}
56
58
  isNotStarted={isNotStarted}
59
+ isPinned={isPinned}
60
+ isChallenge={isChallenge}
57
61
  >
58
- <TaskHeader>
62
+ <TaskHeader isMobile={isMobile}>
59
63
  <TaskHeaderLeft>
60
64
  {iconAtlasJSON && iconAtlasIMG && (
61
65
  <IconWrapper>
@@ -99,7 +103,7 @@ export const DailyTaskItem: React.FC<IDailyTaskItemProps> = ({
99
103
  </TaskHeaderRight>
100
104
  </TaskHeader>
101
105
 
102
- <TaskBody>
106
+ <TaskBody isMobile={isMobile}>
103
107
  <TaskDescription isMobile={isMobile}>
104
108
  <Ellipsis maxWidth="100%" maxLines={isMobile ? 2 : 1}>
105
109
  {task.description}
@@ -122,7 +126,7 @@ export const DailyTaskItem: React.FC<IDailyTaskItemProps> = ({
122
126
  </TaskBody>
123
127
 
124
128
  {isCompleted && !isClaimed && (
125
- <TaskFooter>
129
+ <TaskFooter isMobile={isMobile}>
126
130
  <Button
127
131
  buttonType={ButtonTypes.RPGUIButton}
128
132
  onPointerDown={handleClaimReward}
@@ -147,24 +151,25 @@ const pulseAnimation = keyframes`
147
151
  }
148
152
  `;
149
153
 
150
- const TaskContainer = styled.div<{
154
+ const TaskContainer = styled.div<{
151
155
  isMobile: boolean;
152
156
  isCompleted: boolean;
153
157
  isInProgress: boolean;
154
158
  isNotStarted: boolean;
155
159
  isPinned?: boolean;
160
+ isChallenge?: boolean;
156
161
  }>`
157
- background: rgba(0, 0, 0, 0.6) !important;
158
- border: 1px solid ${props =>
159
- props.isCompleted ? uiColors.green :
160
- props.isInProgress ? uiColors.yellow :
161
- uiColors.darkGray
162
+ background: ${props =>
163
+ props.isChallenge ? 'rgb(209, 39, 42)' :
164
+ props.isPinned ? 'rgba(255, 215, 0, 0.1)' :
165
+ 'rgba(0, 0, 0, 0.6)'
162
166
  } !important;
167
+ border: 1px solid ${uiColors.darkGray} !important;
163
168
  border-radius: ${props => props.isMobile ? '4px' : '6px'};
164
- padding: ${props => props.isMobile ? '6px' : '8px'};
169
+ padding: ${props => props.isMobile ? '10px' : '14px'};
165
170
  display: flex;
166
171
  flex-direction: column;
167
- gap: ${props => props.isMobile ? '4px' : '6px'};
172
+ gap: ${props => props.isMobile ? '8px' : '12px'};
168
173
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
169
174
  transition: all 0.2s ease;
170
175
  font-style: normal;
@@ -173,11 +178,7 @@ const TaskContainer = styled.div<{
173
178
  box-sizing: border-box;
174
179
 
175
180
  /* Task status visual states */
176
- opacity: ${props =>
177
- props.isCompleted ? 1 :
178
- props.isInProgress ? 1 :
179
- 0.6
180
- };
181
+ opacity: 1;
181
182
 
182
183
  ${props => props.isNotStarted && `
183
184
  filter: grayscale(0.7);
@@ -192,26 +193,21 @@ const TaskContainer = styled.div<{
192
193
  }
193
194
 
194
195
  &:hover {
195
- background: ${props =>
196
- props.isPinned ? 'rgba(255, 215, 0, 0.25)' : 'rgba(0, 0, 0, 0.7)'
197
- } !important;
198
- border-color: ${props =>
199
- props.isPinned ? uiColors.yellow :
200
- props.isCompleted ? uiColors.green :
201
- props.isInProgress ? uiColors.yellow :
202
- uiColors.yellow
203
- };
204
- opacity: ${props => props.isNotStarted ? 0.8 : 1};
196
+ background: ${props =>
197
+ props.isPinned ? 'rgba(255, 215, 0, 0.25)' : 'rgba(0, 0, 0, 0.7)'
198
+ } !important;
199
+ border-color: ${uiColors.yellow};
200
+ opacity: 1;
205
201
  }
206
202
  `;
207
203
 
208
- const TaskHeader = styled.div`
204
+ const TaskHeader = styled.div<{ isMobile?: boolean }>`
209
205
  display: flex;
210
206
  width: 100%;
211
207
  justify-content: space-between;
212
208
  align-items: flex-start;
213
209
  border-bottom: 1px solid ${uiColors.darkGray};
214
- padding-bottom: 6px;
210
+ padding-bottom: ${props => props.isMobile ? '8px' : '10px'};
215
211
  min-height: 36px;
216
212
  `;
217
213
 
@@ -270,7 +266,7 @@ const TaskDifficulty = styled.span<{ difficulty: string }>`
270
266
  `;
271
267
 
272
268
  const StatusText = styled.span<{ color: string }>`
273
- color: ${props => props.color};
269
+ color: ${props => props.color} !important;
274
270
  font-size: 0.65rem;
275
271
  font-weight: 500;
276
272
  `;
@@ -286,23 +282,24 @@ const ClaimedBadge = styled.div<{ isMobile: boolean }>`
286
282
  justify-content: center;
287
283
  font-size: ${props => props.isMobile ? '10px' : '12px'};
288
284
  font-weight: bold;
285
+ margin-left: 8px;
289
286
  `;
290
287
 
291
- const TaskBody = styled.div`
288
+ const TaskBody = styled.div<{ isMobile?: boolean }>`
292
289
  display: flex;
293
290
  flex-direction: column;
294
291
  gap: 8px;
295
- padding: 6px 0;
292
+ padding: ${props => props.isMobile ? '4px 0' : '6px 0'};
296
293
  `;
297
294
 
298
295
  const RewardsSection = styled.div`
299
296
  margin-top: 4px;
300
297
  `;
301
298
 
302
- const TaskFooter = styled.div`
299
+ const TaskFooter = styled.div<{ isMobile?: boolean }>`
303
300
  display: flex;
304
301
  justify-content: center;
305
- padding-top: 6px;
302
+ padding-top: ${props => props.isMobile ? '8px' : '10px'};
306
303
  border-top: 1px solid ${uiColors.darkGray};
307
304
  `;
308
305
 
@@ -2,18 +2,18 @@ import {
2
2
  ICharacterDailyTask,
3
3
  ICollectGlobalRewardRequest,
4
4
  ICollectRewardRequest,
5
- TaskType,
6
5
  TaskStatus,
6
+ TaskType,
7
7
  isMobileOrTablet,
8
8
  } from '@rpg-engine/shared';
9
- import React, { useState, useMemo } from 'react';
9
+ import React, { useMemo, useState } from 'react';
10
+ import { FaClipboardList, FaThumbtack } from 'react-icons/fa';
10
11
  import styled from 'styled-components';
11
- import { FaThumbtack, FaClipboardList } from 'react-icons/fa';
12
12
  import { uiColors } from '../../constants/uiColors';
13
13
  import { useLocalStorage } from '../../hooks/useLocalStorage';
14
14
  import { DraggableContainer } from '../DraggableContainer';
15
- import { RPGUIContainerTypes } from '../RPGUI/RPGUIContainer';
16
15
  import { Dropdown, IOptionsProps as DropdownOption } from '../Dropdown';
16
+ import { RPGUIContainerTypes } from '../RPGUI/RPGUIContainer';
17
17
  import { SearchBar } from '../shared/SearchBar/SearchBar';
18
18
  import { DailyTaskItem } from './DailyTaskItem';
19
19
  import { GlobalDailyProgress } from './GlobalDailyProgress';
@@ -50,7 +50,7 @@ export const DailyTasks: React.FC<IDailyTasksProps> = ({
50
50
  const [globalRewardClaimedLocal, setGlobalRewardClaimedLocal] = useState(
51
51
  false
52
52
  );
53
-
53
+
54
54
  // Search and filter state
55
55
  const [searchQuery, setSearchQuery] = useState('');
56
56
  const [selectedStatus, setSelectedStatus] = useState('all');
@@ -72,15 +72,15 @@ export const DailyTasks: React.FC<IDailyTasksProps> = ({
72
72
  const isTaskRewardClaimed = (taskKey: string): boolean => {
73
73
  return claimedTasks.includes(taskKey);
74
74
  };
75
-
75
+
76
76
  const togglePinTask = (taskKey: string) => {
77
- setPinnedTasks(prev =>
77
+ setPinnedTasks(prev =>
78
78
  prev.includes(taskKey)
79
79
  ? prev.filter(key => key !== taskKey)
80
80
  : [...prev, taskKey]
81
81
  );
82
82
  };
83
-
83
+
84
84
  // Filter options using Store pattern
85
85
  const statusOptions: DropdownOption[] = [
86
86
  { id: 0, value: 'all', option: 'All' },
@@ -89,25 +89,25 @@ export const DailyTasks: React.FC<IDailyTasksProps> = ({
89
89
  { id: 3, value: 'inprogress', option: 'In Progress' },
90
90
  { id: 4, value: 'notstarted', option: 'Not Started' },
91
91
  ];
92
-
92
+
93
93
  // Filtered tasks using InformationCenter pattern
94
94
  const filteredTasks = useMemo(() => {
95
95
  let filtered = localTasks.filter(task => {
96
- const matchesSearch =
96
+ const matchesSearch =
97
97
  task.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
98
98
  task.description?.toLowerCase().includes(searchQuery.toLowerCase()) ||
99
99
  task.key.toLowerCase().includes(searchQuery.toLowerCase());
100
-
101
- const matchesStatus =
100
+
101
+ const matchesStatus =
102
102
  selectedStatus === 'all' ||
103
103
  (selectedStatus === 'pinned' && pinnedTasks.includes(task.key)) ||
104
104
  (selectedStatus === 'completed' && task.status === TaskStatus.Completed) ||
105
105
  (selectedStatus === 'inprogress' && task.status === TaskStatus.InProgress) ||
106
106
  (selectedStatus === 'notstarted' && task.status === TaskStatus.NotStarted);
107
-
107
+
108
108
  return matchesSearch && matchesStatus;
109
109
  });
110
-
110
+
111
111
  // Sort with pinned tasks first
112
112
  return filtered.sort((a, b) => {
113
113
  const aIsPinned = pinnedTasks.includes(a.key);
@@ -139,7 +139,7 @@ export const DailyTasks: React.FC<IDailyTasksProps> = ({
139
139
  }
140
140
  />
141
141
  </GlobalProgressFixed>
142
-
142
+
143
143
  <SearchHeader>
144
144
  <SearchBarContainer>
145
145
  <SearchBar
@@ -156,7 +156,7 @@ export const DailyTasks: React.FC<IDailyTasksProps> = ({
156
156
  />
157
157
  </DropdownContainer>
158
158
  </SearchHeader>
159
-
159
+
160
160
  <TasksList className="tasks-container" isMobile={isMobile}>
161
161
  {filteredTasks.length > 0 ? (
162
162
  filteredTasks.map(task => (
@@ -262,14 +262,18 @@ const TasksList = styled.div<{ isMobile: boolean }>`
262
262
 
263
263
  const GlobalProgressFixed = styled.div`
264
264
  flex-shrink: 0;
265
- padding: 8px 12px;
265
+ padding: 12px;
266
266
  background-color: transparent;
267
267
  `;
268
268
 
269
269
  const SearchHeader = styled.div`
270
270
  display: flex;
271
- gap: 12px;
272
- padding: 12px 12px 8px 12px;
271
+ gap: 12px;
272
+ justify-content: center;
273
+ align-items: center;
274
+ margin-left: 12px;
275
+ margin-right: 12px;
276
+ padding: 0.25rem;
273
277
  border-bottom: 1px solid ${uiColors.darkGray};
274
278
  background: rgba(0, 0, 0, 0.3);
275
279
  `;
@@ -291,7 +295,7 @@ const TaskWrapper = styled.div`
291
295
  const PinButton = styled.button<{ isPinned: boolean }>`
292
296
  position: absolute;
293
297
  top: 8px;
294
- right: 8px;
298
+ right: 32px;
295
299
  background: rgba(0, 0, 0, 0.7);
296
300
  color: ${props => props.isPinned ? uiColors.yellow : uiColors.lightGray};
297
301
  border: 1px solid ${props => props.isPinned ? uiColors.yellow : 'transparent'};