rn-vs-lb 1.0.64 → 1.0.66
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/components/Button/Button.stories.tsx +1 -1
- package/components/Button/DeleteAccountButton.stories.tsx +13 -1
- package/components/Button/DeleteAccountButton.tsx +28 -8
- package/components/Button/PostButton.stories.tsx +1 -1
- package/components/Button/TelegramFeedbackLink.stories.tsx +7 -1
- package/components/Button/TelegramFeedbackLink.tsx +12 -4
- package/components/Cards/BusinessIdeaCard.stories.tsx +73 -0
- package/components/Cards/BusinessIdeaCard.tsx +251 -0
- package/components/Cards/EventCard.stories.tsx +4 -1
- package/components/Cards/EventCard.tsx +9 -2
- package/components/Cards/PlaceCard.stories.tsx +1 -1
- package/components/Cards/index.tsx +1 -0
- package/components/Chat/ChatItem.stories.tsx +1 -1
- package/components/Chat/ChatTab/ChatTabs.stories.tsx +1 -1
- package/components/Chat/ChatTab/SubTabButton.stories.tsx +1 -1
- package/components/Chat/InputMessage.stories.tsx +12 -1
- package/components/Chat/InputMessage.tsx +5 -3
- package/components/Chat/MessageItem/MessageItem.stories.tsx +1 -1
- package/components/Chat/PinnedMessagesBar/PinnedMessagesBar.stories.tsx +1 -1
- package/components/Gallery/AiAgentGallery.stories.tsx +1 -1
- package/components/Gallery/ProfileMediaGallery.stories.tsx +66 -0
- package/components/Gallery/ProfileMediaGallery.tsx +239 -0
- package/components/Gallery/ProfileMediaNavigationItem.tsx +73 -0
- package/components/Gallery/ProfileSelfiesGallery.pure.tsx +97 -0
- package/components/Gallery/ProfileSelfiesGallery.stories.tsx +86 -0
- package/components/Gallery/index.ts +4 -1
- package/components/Header/HeaderDefault.stories.tsx +1 -1
- package/components/Header/HeaderEdit.stories.tsx +1 -1
- package/components/Header/HeaderHome.stories.tsx +1 -1
- package/components/Header/HeaderSwitcher.stories.tsx +1 -1
- package/components/Header/HeaderWithImg.stories.tsx +10 -1
- package/components/Header/HeaderWithImg.tsx +27 -7
- package/components/Modals/GalleryModal.stories.tsx +1 -1
- package/components/Modals/GuestAiChatModal.stories.tsx +12 -4
- package/components/Modals/GuestAiChatModal.tsx +9 -3
- package/components/Modals/ReportModal.stories.tsx +35 -2
- package/components/Modals/ReportModal.tsx +23 -24
- package/components/Poll/CommentItem.stories.tsx +1 -1
- package/components/Poll/PollCardList.stories.tsx +5 -1
- package/components/Poll/PollCardList.tsx +4 -2
- package/components/Posts/EventCardList.stories.tsx +1 -1
- package/components/Posts/PlaceCardList.stories.tsx +1 -1
- package/components/Prank/HeroPrankCard.stories.tsx +47 -0
- package/components/Prank/HeroPrankCard.tsx +114 -0
- package/components/Prank/HomelessPrankPage.stories.tsx +58 -0
- package/components/Prank/UploadPromptCard.stories.tsx +55 -0
- package/components/Prank/UploadPromptCard.tsx +130 -0
- package/components/Prank/index.ts +5 -0
- package/components/Profile/ModalProfilePhoto.stories.tsx +1 -1
- package/components/Profile/ProfileCard/ProfileCard.stories.tsx +1 -1
- package/components/Profile/ProfilePhotoBanner.stories.tsx +11 -2
- package/components/Profile/ProfilePhotoBanner.tsx +5 -3
- package/components/Profile/ProfilePhotoUpload/ProfilePhotoUpload.stories.tsx +1 -1
- package/components/Profile/ProfileSummary/ProfileSummary.stories.tsx +52 -0
- package/components/Profile/ProfileSummary/ProfileSummary.tsx +188 -0
- package/components/Profile/ProfileTabs/UserProfileTabs.stories.tsx +1 -1
- package/components/Profile/index.ts +2 -0
- package/components/Screens/AppScreens.stories.tsx +572 -0
- package/components/Screens/HomeScreen.stories.tsx +159 -0
- package/components/Screens/LibraryScreen.stories.tsx +97 -0
- package/components/Settings/AppSettingsScreen.stories.tsx +134 -0
- package/components/Settings/AppSettingsScreen.tsx +215 -0
- package/components/Settings/SettingsHeader.tsx +37 -0
- package/components/Settings/SettingsListItem.tsx +142 -0
- package/components/Settings/SettingsManageAccountButton.tsx +58 -0
- package/components/Settings/SettingsOptionList.tsx +82 -0
- package/components/Settings/SettingsProfileCard.tsx +58 -0
- package/components/Settings/SettingsScreen.stories.tsx +66 -0
- package/components/Settings/SettingsScreen.tsx +129 -0
- package/components/Settings/SettingsSection.tsx +56 -0
- package/components/Settings/SettingsToggleItem.tsx +70 -0
- package/components/Settings/index.ts +23 -0
- package/components/Specialist/Hero.stories.tsx +2 -1
- package/components/Specialist/Hero.tsx +3 -1
- package/components/Specialist/PortfolioCarousel.stories.tsx +1 -1
- package/components/Specialist/ServicesList.stories.tsx +2 -1
- package/components/Specialist/ServicesList.tsx +4 -3
- package/components/Tooltip/DangerTooltip.stories.tsx +1 -1
- package/components/Tooltip/InfoTooltip.stories.tsx +1 -1
- package/components/Tooltip/InfoTooltipBase.stories.tsx +1 -1
- package/components/Tooltip/SucceedTooltip.stories.tsx +1 -1
- package/components/Tooltip/WarningTooltip.stories.tsx +1 -1
- package/components/UI/DeletedState.stories.tsx +6 -1
- package/components/UI/DeletedState.tsx +12 -3
- package/components/UI/DescriptionMore.stories.tsx +2 -0
- package/components/UI/DescriptionMore.tsx +13 -3
- package/components/UI/EmptyState.stories.tsx +4 -1
- package/components/UI/EmptyState.tsx +3 -2
- package/components/UI/HorizontalCardSection.stories.tsx +85 -0
- package/components/UI/HorizontalCardSection.tsx +199 -0
- package/components/UI/NoAuth.stories.tsx +3 -0
- package/components/UI/NoAuth.tsx +7 -6
- package/components/UI/ParticipantItem.stories.tsx +21 -0
- package/components/UI/ParticipantItem.tsx +30 -6
- package/components/UI/TabBar/BottomTabBar.stories.tsx +87 -0
- package/components/UI/TabBar/BottomTabBar.tsx +128 -0
- package/components/UI/ThemeSwitcher.stories.tsx +5 -1
- package/components/UI/ThemeSwitcher.tsx +7 -2
- package/components/UI/UpdateRequiredView.stories.tsx +2 -0
- package/components/UI/UpdateRequiredView.tsx +3 -2
- package/components/UI/index.ts +4 -0
- package/components/UserCards/AiAgentHeroCard.stories.tsx +66 -0
- package/components/UserCards/AiAgentHeroCard.tsx +242 -0
- package/components/UserCards/Organazer.tsx +3 -2
- package/components/UserCards/Organizer.stories.tsx +5 -1
- package/components/UserCards/SpecialistCard.stories.tsx +3 -1
- package/components/UserCards/SpecialistCard.tsx +3 -2
- package/components/UserCards/StoryCard.stories.tsx +1 -1
- package/components/UserCards/UserProfileCard.stories.tsx +1 -1
- package/components/UserCards/UserRow.stories.tsx +1 -1
- package/components/UserCards/index.ts +2 -0
- package/components/index.ts +2 -0
- package/package.json +2 -1
|
@@ -4,7 +4,7 @@ import { Text, TouchableOpacity, View } from 'react-native';
|
|
|
4
4
|
import HeaderDefault, { AccessType } from './HeaderDefault';
|
|
5
5
|
|
|
6
6
|
const meta: Meta = {
|
|
7
|
-
title: 'Header/HeaderDefault',
|
|
7
|
+
title: 'Layout/Header/HeaderDefault',
|
|
8
8
|
component: HeaderDefault,
|
|
9
9
|
args: {
|
|
10
10
|
title: 'Community event',
|
|
@@ -4,7 +4,7 @@ import { Text, View } from 'react-native';
|
|
|
4
4
|
import { HeaderHome } from './HeaderHome';
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof HeaderHome> = {
|
|
7
|
-
title: 'Header/HeaderHome',
|
|
7
|
+
title: 'Layout/Header/HeaderHome',
|
|
8
8
|
component: HeaderHome,
|
|
9
9
|
argTypes: {
|
|
10
10
|
onPress: { action: 'header press' },
|
|
@@ -4,7 +4,7 @@ import { View, Text } from 'react-native';
|
|
|
4
4
|
import { HeaderSwitcher } from './HeaderSwitcher';
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof HeaderSwitcher> = {
|
|
7
|
-
title: 'Header/HeaderSwitcher',
|
|
7
|
+
title: 'Layout/Header/HeaderSwitcher',
|
|
8
8
|
component: HeaderSwitcher,
|
|
9
9
|
args: {
|
|
10
10
|
isFirst: true,
|
|
@@ -4,7 +4,7 @@ import { View } from 'react-native';
|
|
|
4
4
|
import HeaderWithImg from './HeaderWithImg';
|
|
5
5
|
|
|
6
6
|
const meta: Meta = {
|
|
7
|
-
title: 'Header/HeaderWithImg',
|
|
7
|
+
title: 'Layout/Header/HeaderWithImg',
|
|
8
8
|
component: HeaderWithImg,
|
|
9
9
|
args: {
|
|
10
10
|
imgUrl: 'https://placekitten.com/200/200',
|
|
@@ -16,6 +16,15 @@ const meta: Meta = {
|
|
|
16
16
|
userName: 'Alex Johnson',
|
|
17
17
|
},
|
|
18
18
|
],
|
|
19
|
+
typingText: 'typing…',
|
|
20
|
+
onlineText: 'Online',
|
|
21
|
+
offlineText: 'Offline',
|
|
22
|
+
groupTypingSuffix: ': typing…',
|
|
23
|
+
backAccessibilityLabel: 'Back',
|
|
24
|
+
imageAccessibilityLabel: 'Open chat image',
|
|
25
|
+
actionsAccessibilityLabel: 'More actions',
|
|
26
|
+
onlineStatusAccessibilityLabel: 'online',
|
|
27
|
+
offlineStatusAccessibilityLabel: 'offline',
|
|
19
28
|
},
|
|
20
29
|
argTypes: {
|
|
21
30
|
onBackPress: { action: 'back' },
|
|
@@ -22,6 +22,15 @@ interface HeaderProps {
|
|
|
22
22
|
isOnline?: boolean;
|
|
23
23
|
isTyping?: boolean;
|
|
24
24
|
typingUserName?: string;
|
|
25
|
+
typingText: string;
|
|
26
|
+
onlineText: string;
|
|
27
|
+
offlineText: string;
|
|
28
|
+
groupTypingSuffix: string;
|
|
29
|
+
backAccessibilityLabel: string;
|
|
30
|
+
imageAccessibilityLabel: string;
|
|
31
|
+
actionsAccessibilityLabel: string;
|
|
32
|
+
onlineStatusAccessibilityLabel: string;
|
|
33
|
+
offlineStatusAccessibilityLabel: string;
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
const HeaderWithImg: React.FC<HeaderProps> = ({
|
|
@@ -35,6 +44,15 @@ const HeaderWithImg: React.FC<HeaderProps> = ({
|
|
|
35
44
|
isOnline = false,
|
|
36
45
|
isTyping = false,
|
|
37
46
|
typingUserName,
|
|
47
|
+
typingText,
|
|
48
|
+
onlineText,
|
|
49
|
+
offlineText,
|
|
50
|
+
groupTypingSuffix,
|
|
51
|
+
backAccessibilityLabel,
|
|
52
|
+
imageAccessibilityLabel,
|
|
53
|
+
actionsAccessibilityLabel,
|
|
54
|
+
onlineStatusAccessibilityLabel,
|
|
55
|
+
offlineStatusAccessibilityLabel,
|
|
38
56
|
}) => {
|
|
39
57
|
const { globalStyleSheet, theme, sizes, commonStyles, typography } = useTheme();
|
|
40
58
|
const styles = useMemo(
|
|
@@ -46,7 +64,7 @@ const HeaderWithImg: React.FC<HeaderProps> = ({
|
|
|
46
64
|
|
|
47
65
|
return (
|
|
48
66
|
<View style={styles.container}>
|
|
49
|
-
<TouchableOpacity onPress={onBackPress} accessibilityRole="button" accessibilityLabel=
|
|
67
|
+
<TouchableOpacity onPress={onBackPress} accessibilityRole="button" accessibilityLabel={backAccessibilityLabel}>
|
|
50
68
|
<Ionicons name="arrow-back" size={24} color={theme.text} />
|
|
51
69
|
</TouchableOpacity>
|
|
52
70
|
|
|
@@ -56,7 +74,7 @@ const HeaderWithImg: React.FC<HeaderProps> = ({
|
|
|
56
74
|
style={globalStyleSheet.flexRowCenter}
|
|
57
75
|
onPress={onImgPress}
|
|
58
76
|
accessibilityRole="imagebutton"
|
|
59
|
-
accessibilityLabel=
|
|
77
|
+
accessibilityLabel={imageAccessibilityLabel}
|
|
60
78
|
activeOpacity={0.8}
|
|
61
79
|
>
|
|
62
80
|
<Image source={{ uri: imgUrl }} style={styles.photo} />
|
|
@@ -69,15 +87,17 @@ const HeaderWithImg: React.FC<HeaderProps> = ({
|
|
|
69
87
|
{/* отображение статусов */}
|
|
70
88
|
{!isGroupChat ? (
|
|
71
89
|
isTyping ? (
|
|
72
|
-
<Text style={[typography.body, styles.subtitleItalic]}>
|
|
90
|
+
<Text style={[typography.body, styles.subtitleItalic]}>{typingText}</Text>
|
|
73
91
|
) : (
|
|
74
92
|
<View style={styles.statusRow}>
|
|
75
93
|
<Text style={[typography.body, styles.subtitleItalic]}>
|
|
76
|
-
{isOnline ?
|
|
94
|
+
{isOnline ? onlineText : offlineText}
|
|
77
95
|
</Text>
|
|
78
96
|
<View
|
|
79
97
|
style={[styles.statusDot, isOnline ? styles.online : styles.offline]}
|
|
80
|
-
accessibilityLabel={
|
|
98
|
+
accessibilityLabel={
|
|
99
|
+
isOnline ? onlineStatusAccessibilityLabel : offlineStatusAccessibilityLabel
|
|
100
|
+
}
|
|
81
101
|
/>
|
|
82
102
|
</View>
|
|
83
103
|
)
|
|
@@ -87,7 +107,7 @@ const HeaderWithImg: React.FC<HeaderProps> = ({
|
|
|
87
107
|
ellipsizeMode="tail"
|
|
88
108
|
style={[typography.body, styles.subtitleItalic]}
|
|
89
109
|
>
|
|
90
|
-
{typingUserName}
|
|
110
|
+
{`${typingUserName}${groupTypingSuffix}`}
|
|
91
111
|
</Text>
|
|
92
112
|
) : null}
|
|
93
113
|
</View>
|
|
@@ -99,7 +119,7 @@ const HeaderWithImg: React.FC<HeaderProps> = ({
|
|
|
99
119
|
style={styles.actionButton}
|
|
100
120
|
onPress={onActionPress}
|
|
101
121
|
accessibilityRole="button"
|
|
102
|
-
accessibilityLabel=
|
|
122
|
+
accessibilityLabel={actionsAccessibilityLabel}
|
|
103
123
|
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
104
124
|
>
|
|
105
125
|
<Ionicons name="ellipsis-horizontal-sharp" size={20} color={theme.primary} />
|
|
@@ -10,7 +10,7 @@ const IMAGES = [
|
|
|
10
10
|
];
|
|
11
11
|
|
|
12
12
|
const meta = {
|
|
13
|
-
title: 'Modals/GalleryModal',
|
|
13
|
+
title: 'Features/Modals/GalleryModal',
|
|
14
14
|
component: GalleryModal,
|
|
15
15
|
decorators: [(Story) => <View style={{ flex: 1 }}><Story /></View>],
|
|
16
16
|
argTypes: { onRequestClose: { action: 'onRequestClose' } },
|
|
@@ -21,8 +21,10 @@ const sampleMessages: PureChatMessage[] = [
|
|
|
21
21
|
},
|
|
22
22
|
];
|
|
23
23
|
|
|
24
|
+
const defaultLimitLabel = (remaining: number, limit: number) => `Осталось сообщений: ${remaining} / ${limit}`;
|
|
25
|
+
|
|
24
26
|
const meta = {
|
|
25
|
-
title: 'Modals/GuestAiChatModal',
|
|
27
|
+
title: 'Features/Modals/GuestAiChatModal',
|
|
26
28
|
component: GuestAiChatModalView,
|
|
27
29
|
argTypes: {
|
|
28
30
|
onClose: { action: 'close modal' },
|
|
@@ -36,6 +38,7 @@ const meta = {
|
|
|
36
38
|
theme: { table: { disable: true } },
|
|
37
39
|
typography: { table: { disable: true } },
|
|
38
40
|
sizes: { table: { disable: true } },
|
|
41
|
+
limitLabel: { table: { disable: true } },
|
|
39
42
|
},
|
|
40
43
|
args: {
|
|
41
44
|
visible: true,
|
|
@@ -49,6 +52,9 @@ const meta = {
|
|
|
49
52
|
theme,
|
|
50
53
|
typography,
|
|
51
54
|
sizes: SIZES,
|
|
55
|
+
defaultBotName: 'AI-бот',
|
|
56
|
+
limitLabel: defaultLimitLabel,
|
|
57
|
+
inputPlaceholder: 'Спросите что-нибудь...'
|
|
52
58
|
},
|
|
53
59
|
decorators: [
|
|
54
60
|
(StoryComponent) => (
|
|
@@ -174,9 +180,11 @@ Playground.args = {
|
|
|
174
180
|
remaining: 5,
|
|
175
181
|
};
|
|
176
182
|
|
|
177
|
-
export const DefaultOpen: StoryFn<GuestAiChatProps> =
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
export const DefaultOpen: StoryFn<GuestAiChatProps> = {
|
|
184
|
+
render: Template,
|
|
185
|
+
args: {
|
|
186
|
+
visible: true,
|
|
187
|
+
},
|
|
180
188
|
};
|
|
181
189
|
|
|
182
190
|
export const WithErrorState: StoryFn<GuestAiChatProps> = (args) => (
|
|
@@ -32,6 +32,9 @@ export type GuestAiChatViewProps = {
|
|
|
32
32
|
isSending: boolean;
|
|
33
33
|
limit?: number;
|
|
34
34
|
remaining?: number;
|
|
35
|
+
defaultBotName: string;
|
|
36
|
+
limitLabel: (remaining: number, limit: number) => string;
|
|
37
|
+
inputPlaceholder: string;
|
|
35
38
|
|
|
36
39
|
// экшены
|
|
37
40
|
onChangeInput: (v: string) => void;
|
|
@@ -57,6 +60,9 @@ export const GuestAiChatModalView: FC<GuestAiChatViewProps> = memo(
|
|
|
57
60
|
isSending,
|
|
58
61
|
limit,
|
|
59
62
|
remaining,
|
|
63
|
+
defaultBotName,
|
|
64
|
+
limitLabel,
|
|
65
|
+
inputPlaceholder,
|
|
60
66
|
onChangeInput,
|
|
61
67
|
onSend,
|
|
62
68
|
listRef,
|
|
@@ -92,10 +98,10 @@ export const GuestAiChatModalView: FC<GuestAiChatViewProps> = memo(
|
|
|
92
98
|
<View style={styles.modalContainer}>
|
|
93
99
|
<View style={styles.header}>
|
|
94
100
|
<View>
|
|
95
|
-
<Text style={typography.titleH6}>{botName ||
|
|
101
|
+
<Text style={typography.titleH6}>{botName || defaultBotName}</Text>
|
|
96
102
|
{limit !== undefined && remaining !== undefined && (
|
|
97
103
|
<Text style={styles.limitText}>
|
|
98
|
-
|
|
104
|
+
{limitLabel(remaining, limit)}
|
|
99
105
|
</Text>
|
|
100
106
|
)}
|
|
101
107
|
</View>
|
|
@@ -118,7 +124,7 @@ export const GuestAiChatModalView: FC<GuestAiChatViewProps> = memo(
|
|
|
118
124
|
<View style={styles.inputRow}>
|
|
119
125
|
<TextInput
|
|
120
126
|
style={styles.input}
|
|
121
|
-
placeholder=
|
|
127
|
+
placeholder={inputPlaceholder}
|
|
122
128
|
placeholderTextColor={theme.greyText}
|
|
123
129
|
value={inputValue}
|
|
124
130
|
onChangeText={onChangeInput}
|
|
@@ -13,8 +13,25 @@ const submitLogger = (payload: { reason: string; details?: string }) => {
|
|
|
13
13
|
console.log('[storybook:report-modal:submit]', payload);
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
const userReasonOptions = [
|
|
17
|
+
'Spam or scam',
|
|
18
|
+
'Harassment or bullying',
|
|
19
|
+
'Inappropriate content',
|
|
20
|
+
'Fake profile',
|
|
21
|
+
'Other',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const postReasonOptions = [
|
|
25
|
+
'Spam or misleading',
|
|
26
|
+
'Hate speech or discrimination',
|
|
27
|
+
'Violence or threats',
|
|
28
|
+
'Sexually explicit content',
|
|
29
|
+
'Harassment or bullying',
|
|
30
|
+
'Other',
|
|
31
|
+
];
|
|
32
|
+
|
|
16
33
|
const meta: Meta<ReportModalProps> = {
|
|
17
|
-
title: 'Modals/ReportModal',
|
|
34
|
+
title: 'Features/Modals/ReportModal',
|
|
18
35
|
component: ReportModal,
|
|
19
36
|
argTypes: {
|
|
20
37
|
type: {
|
|
@@ -92,9 +109,18 @@ const Template: StoryFn<ReportModalProps> = (args) => {
|
|
|
92
109
|
);
|
|
93
110
|
};
|
|
94
111
|
|
|
95
|
-
const baseArgs: Pick<
|
|
112
|
+
const baseArgs: Pick<
|
|
113
|
+
ReportModalProps,
|
|
114
|
+
'visible' | 'type' | 'title' | 'userReasons' | 'postReasons' | 'inputPlaceholder' | 'cancelText' | 'submitText'
|
|
115
|
+
> = {
|
|
96
116
|
visible: true,
|
|
97
117
|
type: 'user',
|
|
118
|
+
title: 'Report User',
|
|
119
|
+
userReasons: userReasonOptions,
|
|
120
|
+
postReasons: postReasonOptions,
|
|
121
|
+
inputPlaceholder: 'Additional details (optional)',
|
|
122
|
+
cancelText: 'Cancel',
|
|
123
|
+
submitText: 'Send',
|
|
98
124
|
};
|
|
99
125
|
|
|
100
126
|
export const UserReport: StoryFn<ReportModalProps> = Template.bind({});
|
|
@@ -113,6 +139,7 @@ export const PostReport: StoryFn<ReportModalProps> = Template.bind({});
|
|
|
113
139
|
PostReport.args = {
|
|
114
140
|
...baseArgs,
|
|
115
141
|
type: 'post',
|
|
142
|
+
title: 'Report Post',
|
|
116
143
|
};
|
|
117
144
|
PostReport.parameters = {
|
|
118
145
|
docs: {
|
|
@@ -160,6 +187,7 @@ export const InteractivePlayground: StoryFn<ReportModalProps> = (args) => {
|
|
|
160
187
|
{...args}
|
|
161
188
|
visible={isVisible}
|
|
162
189
|
type={reportType}
|
|
190
|
+
title={reportType === 'user' ? 'Report User' : 'Report Post'}
|
|
163
191
|
onClose={() => {
|
|
164
192
|
closeLogger();
|
|
165
193
|
setIsVisible(false);
|
|
@@ -170,6 +198,11 @@ export const InteractivePlayground: StoryFn<ReportModalProps> = (args) => {
|
|
|
170
198
|
setIsVisible(false);
|
|
171
199
|
args.onSubmit(reason, details);
|
|
172
200
|
}}
|
|
201
|
+
userReasons={userReasonOptions}
|
|
202
|
+
postReasons={postReasonOptions}
|
|
203
|
+
inputPlaceholder={args.inputPlaceholder}
|
|
204
|
+
cancelText={args.cancelText}
|
|
205
|
+
submitText={args.submitText}
|
|
173
206
|
/>
|
|
174
207
|
</View>
|
|
175
208
|
);
|
|
@@ -16,26 +16,25 @@ type Props = {
|
|
|
16
16
|
onClose: () => void;
|
|
17
17
|
onSubmit: (reason: string, details: string) => void;
|
|
18
18
|
type: "user" | "post";
|
|
19
|
+
title: string;
|
|
20
|
+
userReasons: string[];
|
|
21
|
+
postReasons: string[];
|
|
22
|
+
inputPlaceholder: string;
|
|
23
|
+
cancelText: string;
|
|
24
|
+
submitText: string;
|
|
19
25
|
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
'Violence or threats',
|
|
33
|
-
'Sexually explicit content',
|
|
34
|
-
'Harassment or bullying',
|
|
35
|
-
'Other',
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
const ReportModal: React.FC<Props> = ({ visible, onClose, onSubmit, type }) => {
|
|
26
|
+
const ReportModal: React.FC<Props> = ({
|
|
27
|
+
visible,
|
|
28
|
+
onClose,
|
|
29
|
+
onSubmit,
|
|
30
|
+
type,
|
|
31
|
+
title,
|
|
32
|
+
userReasons,
|
|
33
|
+
postReasons,
|
|
34
|
+
inputPlaceholder,
|
|
35
|
+
cancelText,
|
|
36
|
+
submitText,
|
|
37
|
+
}) => {
|
|
39
38
|
const { theme } = useTheme();
|
|
40
39
|
const styles = getStyles({ theme });
|
|
41
40
|
|
|
@@ -50,7 +49,7 @@ const ReportModal: React.FC<Props> = ({ visible, onClose, onSubmit, type }) => {
|
|
|
50
49
|
onClose();
|
|
51
50
|
};
|
|
52
51
|
|
|
53
|
-
const reasons = type === "user" ?
|
|
52
|
+
const reasons = type === "user" ? userReasons : postReasons;
|
|
54
53
|
|
|
55
54
|
return (
|
|
56
55
|
<Modal
|
|
@@ -61,7 +60,7 @@ const ReportModal: React.FC<Props> = ({ visible, onClose, onSubmit, type }) => {
|
|
|
61
60
|
>
|
|
62
61
|
<View style={styles.overlay}>
|
|
63
62
|
<View style={styles.container}>
|
|
64
|
-
<Text style={styles.title}>
|
|
63
|
+
<Text style={styles.title}>{title}</Text>
|
|
65
64
|
<ScrollView style={styles.reasonsContainer}>
|
|
66
65
|
{reasons.map((reason) => (
|
|
67
66
|
<TouchableOpacity
|
|
@@ -86,7 +85,7 @@ const ReportModal: React.FC<Props> = ({ visible, onClose, onSubmit, type }) => {
|
|
|
86
85
|
|
|
87
86
|
<TextInput
|
|
88
87
|
style={styles.input}
|
|
89
|
-
placeholder=
|
|
88
|
+
placeholder={inputPlaceholder}
|
|
90
89
|
placeholderTextColor="#888"
|
|
91
90
|
value={details}
|
|
92
91
|
onChangeText={setDetails}
|
|
@@ -96,7 +95,7 @@ const ReportModal: React.FC<Props> = ({ visible, onClose, onSubmit, type }) => {
|
|
|
96
95
|
|
|
97
96
|
<View style={styles.actions}>
|
|
98
97
|
<TouchableOpacity style={styles.cancelBtn} onPress={onClose}>
|
|
99
|
-
<Text style={styles.cancelText}>
|
|
98
|
+
<Text style={styles.cancelText}>{cancelText}</Text>
|
|
100
99
|
</TouchableOpacity>
|
|
101
100
|
<TouchableOpacity
|
|
102
101
|
style={[
|
|
@@ -106,7 +105,7 @@ const ReportModal: React.FC<Props> = ({ visible, onClose, onSubmit, type }) => {
|
|
|
106
105
|
disabled={!selectedReason}
|
|
107
106
|
onPress={handleSend}
|
|
108
107
|
>
|
|
109
|
-
<Text style={styles.submitText}>
|
|
108
|
+
<Text style={styles.submitText}>{submitText}</Text>
|
|
110
109
|
</TouchableOpacity>
|
|
111
110
|
</View>
|
|
112
111
|
</View>
|
|
@@ -4,7 +4,7 @@ import { View } from 'react-native';
|
|
|
4
4
|
import PollCardList from './PollCardList';
|
|
5
5
|
|
|
6
6
|
const meta: Meta<React.ComponentProps<typeof PollCardList>> = {
|
|
7
|
-
title: 'Poll/PollCardList',
|
|
7
|
+
title: 'Features/Poll/PollCardList',
|
|
8
8
|
component: PollCardList,
|
|
9
9
|
decorators: [
|
|
10
10
|
(Story) => (
|
|
@@ -29,6 +29,7 @@ Default.args = {
|
|
|
29
29
|
creatorAvatar: 'https://i.pravatar.cc/150?img=11',
|
|
30
30
|
votesCount: 42,
|
|
31
31
|
createdAt: '2 days ago',
|
|
32
|
+
votesLabel: 'votes',
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
export const WithLongQuestion = Template.bind({});
|
|
@@ -39,6 +40,7 @@ WithLongQuestion.args = {
|
|
|
39
40
|
creatorAvatar: 'https://i.pravatar.cc/150?img=5',
|
|
40
41
|
votesCount: 128,
|
|
41
42
|
createdAt: '5 hours ago',
|
|
43
|
+
votesLabel: 'votes',
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
export const WithoutDate = Template.bind({});
|
|
@@ -48,6 +50,7 @@ WithoutDate.args = {
|
|
|
48
50
|
creatorAvatar: 'https://i.pravatar.cc/150?img=24',
|
|
49
51
|
votesCount: 8,
|
|
50
52
|
createdAt: null,
|
|
53
|
+
votesLabel: 'votes',
|
|
51
54
|
};
|
|
52
55
|
|
|
53
56
|
export const MinimalInfo = Template.bind({});
|
|
@@ -57,4 +60,5 @@ MinimalInfo.args = {
|
|
|
57
60
|
creatorAvatar: 'https://i.pravatar.cc/150?img=36',
|
|
58
61
|
votesCount: 230,
|
|
59
62
|
createdAt: 'just now',
|
|
63
|
+
votesLabel: 'votes',
|
|
60
64
|
};
|
|
@@ -9,6 +9,7 @@ interface PollCardProps {
|
|
|
9
9
|
votesCount: number;
|
|
10
10
|
onPress?: () => void;
|
|
11
11
|
createdAt: string | null;
|
|
12
|
+
votesLabel: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
const PollCardList: React.FC<PollCardProps> = ({
|
|
@@ -17,7 +18,8 @@ const PollCardList: React.FC<PollCardProps> = ({
|
|
|
17
18
|
creatorAvatar,
|
|
18
19
|
votesCount,
|
|
19
20
|
onPress,
|
|
20
|
-
createdAt
|
|
21
|
+
createdAt,
|
|
22
|
+
votesLabel,
|
|
21
23
|
}) => {
|
|
22
24
|
const { globalStyleSheet, commonStyles, typography } = useTheme();
|
|
23
25
|
const styles = getStyles({ commonStyles });
|
|
@@ -33,7 +35,7 @@ const PollCardList: React.FC<PollCardProps> = ({
|
|
|
33
35
|
</View>
|
|
34
36
|
<Text style={typography.bodyXs}>{creatorName}</Text>
|
|
35
37
|
<View style={globalStyleSheet.flexRowCenterBetween}>
|
|
36
|
-
<Text style={typography.bodyXs}>{votesCount}
|
|
38
|
+
<Text style={typography.bodyXs}>{votesCount} {votesLabel}</Text>
|
|
37
39
|
<Text style={typography.bodyXs}>{createdAt}</Text>
|
|
38
40
|
</View>
|
|
39
41
|
</View>
|
|
@@ -7,7 +7,7 @@ import EventCardList from './EventCardList';
|
|
|
7
7
|
type Props = React.ComponentProps<typeof EventCardList>;
|
|
8
8
|
|
|
9
9
|
const meta: Meta<Props> = {
|
|
10
|
-
title: 'Posts/EventCardList',
|
|
10
|
+
title: 'Features/Posts/EventCardList',
|
|
11
11
|
component: EventCardList,
|
|
12
12
|
decorators: [
|
|
13
13
|
(Story) => (
|
|
@@ -4,7 +4,7 @@ import { View } from 'react-native';
|
|
|
4
4
|
import PlaceCardList from './PlaceCardList';
|
|
5
5
|
|
|
6
6
|
const meta: Meta<React.ComponentProps<typeof PlaceCardList>> = {
|
|
7
|
-
title: 'Posts/PlaceCardList',
|
|
7
|
+
title: 'Features/Posts/PlaceCardList',
|
|
8
8
|
component: PlaceCardList,
|
|
9
9
|
decorators: [
|
|
10
10
|
(Story) => (
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { ThemeProvider } from '../../theme';
|
|
6
|
+
import HeroPrankCard from './HeroPrankCard';
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof HeroPrankCard> = {
|
|
9
|
+
title: 'Features/Prank/HeroPrankCard',
|
|
10
|
+
component: HeroPrankCard,
|
|
11
|
+
decorators: [
|
|
12
|
+
(Story) => (
|
|
13
|
+
<ThemeProvider>
|
|
14
|
+
<View style={{ padding: 24, backgroundColor: '#070C1F', flex: 1 }}>
|
|
15
|
+
<Story />
|
|
16
|
+
</View>
|
|
17
|
+
</ThemeProvider>
|
|
18
|
+
),
|
|
19
|
+
],
|
|
20
|
+
args: {
|
|
21
|
+
imageUri:
|
|
22
|
+
'https://images.unsplash.com/photo-1621447462558-42b4d8bc5d9b?auto=format&fit=crop&w=900&q=80',
|
|
23
|
+
title: 'Homeless Prank',
|
|
24
|
+
description: 'Prank your loved ones with a unknown guest in your home!',
|
|
25
|
+
},
|
|
26
|
+
parameters: {
|
|
27
|
+
backgrounds: {
|
|
28
|
+
default: 'dark',
|
|
29
|
+
values: [
|
|
30
|
+
{ name: 'dark', value: '#070C1F' },
|
|
31
|
+
{ name: 'light', value: '#f5f5f5' },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default meta;
|
|
38
|
+
|
|
39
|
+
type Story = StoryObj<typeof HeroPrankCard>;
|
|
40
|
+
|
|
41
|
+
export const Default: Story = {};
|
|
42
|
+
|
|
43
|
+
export const WithAction: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
onPress: () => console.log('Hero card pressed'),
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ImageBackground,
|
|
4
|
+
StyleProp,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
Text,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
View,
|
|
9
|
+
ViewStyle,
|
|
10
|
+
} from 'react-native';
|
|
11
|
+
import { LinearGradient } from 'expo-linear-gradient';
|
|
12
|
+
|
|
13
|
+
import { ThemeType, SizesType, useTheme } from '../../theme';
|
|
14
|
+
|
|
15
|
+
export interface HeroPrankCardProps {
|
|
16
|
+
imageUri: string;
|
|
17
|
+
title: string;
|
|
18
|
+
description: string;
|
|
19
|
+
onPress?: () => void;
|
|
20
|
+
style?: StyleProp<ViewStyle>;
|
|
21
|
+
testID?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const HeroPrankCard: React.FC<HeroPrankCardProps> = ({
|
|
25
|
+
imageUri,
|
|
26
|
+
title,
|
|
27
|
+
description,
|
|
28
|
+
onPress,
|
|
29
|
+
style,
|
|
30
|
+
testID,
|
|
31
|
+
}) => {
|
|
32
|
+
const { theme, sizes } = useTheme();
|
|
33
|
+
const styles = React.useMemo(() => getStyles({ theme, sizes }), [theme, sizes]);
|
|
34
|
+
|
|
35
|
+
const content = (
|
|
36
|
+
<ImageBackground
|
|
37
|
+
source={{ uri: imageUri }}
|
|
38
|
+
style={styles.imageBackground}
|
|
39
|
+
imageStyle={styles.image}
|
|
40
|
+
accessibilityLabel={title}
|
|
41
|
+
>
|
|
42
|
+
<LinearGradient
|
|
43
|
+
colors={['rgba(0,0,0,0.05)', 'rgba(0,0,0,0.7)', 'rgba(0,0,0,0.95)']}
|
|
44
|
+
style={StyleSheet.absoluteFillObject}
|
|
45
|
+
/>
|
|
46
|
+
<View style={styles.textContainer}>
|
|
47
|
+
<Text style={styles.title} numberOfLines={2}>
|
|
48
|
+
{title}
|
|
49
|
+
</Text>
|
|
50
|
+
<Text style={styles.description} numberOfLines={2}>
|
|
51
|
+
{description}
|
|
52
|
+
</Text>
|
|
53
|
+
</View>
|
|
54
|
+
</ImageBackground>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (onPress) {
|
|
58
|
+
return (
|
|
59
|
+
<TouchableOpacity
|
|
60
|
+
activeOpacity={0.85}
|
|
61
|
+
onPress={onPress}
|
|
62
|
+
style={[styles.container, style]}
|
|
63
|
+
testID={testID}
|
|
64
|
+
>
|
|
65
|
+
{content}
|
|
66
|
+
</TouchableOpacity>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<View style={[styles.container, style]} testID={testID}>
|
|
72
|
+
{content}
|
|
73
|
+
</View>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
interface StyleParams {
|
|
78
|
+
theme: ThemeType;
|
|
79
|
+
sizes: SizesType;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const getStyles = ({ theme, sizes }: StyleParams) =>
|
|
83
|
+
StyleSheet.create({
|
|
84
|
+
container: {
|
|
85
|
+
borderRadius: sizes.radius_lg,
|
|
86
|
+
overflow: 'hidden',
|
|
87
|
+
backgroundColor: theme.black,
|
|
88
|
+
},
|
|
89
|
+
imageBackground: {
|
|
90
|
+
height: 320,
|
|
91
|
+
justifyContent: 'flex-end',
|
|
92
|
+
},
|
|
93
|
+
image: {
|
|
94
|
+
borderRadius: sizes.radius_lg,
|
|
95
|
+
},
|
|
96
|
+
textContainer: {
|
|
97
|
+
paddingHorizontal: sizes.lg,
|
|
98
|
+
paddingVertical: sizes.xl,
|
|
99
|
+
},
|
|
100
|
+
title: {
|
|
101
|
+
fontSize: sizes.h4,
|
|
102
|
+
lineHeight: 30,
|
|
103
|
+
fontWeight: '700',
|
|
104
|
+
color: theme.white,
|
|
105
|
+
},
|
|
106
|
+
description: {
|
|
107
|
+
marginTop: sizes.xs,
|
|
108
|
+
fontSize: sizes.font,
|
|
109
|
+
lineHeight: 22,
|
|
110
|
+
color: 'rgba(255,255,255,0.82)',
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export default HeroPrankCard;
|