@xetwa/design-system 1.0.38 → 1.0.39

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": "@xetwa/design-system",
3
- "version": "1.0.38",
3
+ "version": "1.0.39",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -75,6 +75,19 @@ export const ActiveDark: Story = {
75
75
  subtitle: 'Regatear, números, comida',
76
76
  subtext: '• 3/5',
77
77
  tagLabel: 'AULA MARCADA',
78
+ onSchedulePress: () => console.log('Agendar Aula'),
79
+ onReviewPress: () => console.log('Rever'),
80
+ },
81
+ };
82
+
83
+ export const ExamMode: Story = {
84
+ args: {
85
+ status: 'active-dark',
86
+ title: 'No mercado de Dakar',
87
+ subtitle: 'Exame de módulo',
88
+ subtext: '• 3/5',
89
+ tagLabel: 'POR FAZER',
90
+ onExamPress: () => console.log('Fazer Exame'),
78
91
  },
79
92
  };
80
93
 
@@ -129,6 +142,16 @@ export const Grid: Story = {
129
142
  subtitle="Conversação e prática"
130
143
  subtext="• 4/4"
131
144
  tagLabel="AULA MARCADA"
145
+ onSchedulePress={() => {}}
146
+ onReviewPress={() => {}}
147
+ />
148
+ <ModuleCard
149
+ status="active-dark"
150
+ title="No mercado de Dakar"
151
+ subtitle="Exame de módulo"
152
+ subtext="• 3/5"
153
+ tagLabel="POR FAZER"
154
+ onExamPress={() => {}}
132
155
  />
133
156
  </View>
134
157
  ),
@@ -4,7 +4,7 @@ import { theme } from '../../../styles/theme';
4
4
  import { Tag } from '../../DataDisplay/Tag/Tag';
5
5
  import { ProgressBar } from '../../DataDisplay/ProgressBar/ProgressBar';
6
6
  import { Badge } from '../../DataDisplay/Badge/Badge';
7
- import { Lock, Check, GraduationCap, RotateCcw, CalendarPlus } from 'lucide-react-native';
7
+ import { Lock, Check, GraduationCap, RotateCcw, CalendarPlus, PenTool } from 'lucide-react-native';
8
8
  import { useResponsive } from '../../../hooks/useResponsive';
9
9
  import { Typography } from '../../Typography/Typography';
10
10
  import React, { useRef } from 'react';
@@ -16,7 +16,7 @@ export type ModuleCardStatus = 'active' | 'locked' | 'completed' | 'dark' | 'act
16
16
  *
17
17
  * Regras de Animação e Clique:
18
18
  * - `active`: O cartão como um todo tem animação de escala e é clicável via `onPress`.
19
- * - `active-dark`: O cartão é estático. Apenas os botões internos de "Agendar" (`onSchedulePress`) e "Rever" (`onReviewPress`) têm animação individual.
19
+ * - `active-dark`: O cartão é estático. Apenas os botões internos de "Agendar" (`onSchedulePress`), "Exame" (`onExamPress`) e "Rever" (`onReviewPress`) têm animação individual quando fornecidos.
20
20
  * - `completed`: O cartão é estático. Apenas o ícone/botão superior direito de "Rever" (`onReviewPress`) tem animação individual.
21
21
  * - `locked` / `dark`: O cartão não é interativo.
22
22
  */
@@ -47,6 +47,8 @@ export interface ModuleCardProps {
47
47
  style?: ViewStyle | ViewStyle[];
48
48
  /** Função de clique no botão de Agendar (modo active/dark). */
49
49
  onSchedulePress?: () => void;
50
+ /** Função de clique no botão principal de Exame (modo active/dark). */
51
+ onExamPress?: () => void;
50
52
  /** Função de clique no botão de Rever (modo completed/active/dark). */
51
53
  onReviewPress?: () => void;
52
54
  }
@@ -66,12 +68,14 @@ export const ModuleCard = ({
66
68
  onPress,
67
69
  style,
68
70
  onSchedulePress,
71
+ onExamPress,
69
72
  onReviewPress,
70
73
  }: ModuleCardProps) => {
71
74
  const { scale, scaleText, width } = useResponsive();
72
75
  const isMobileScreen = width < 400;
73
76
 
74
77
  const scheduleScale = useRef(new Animated.Value(1)).current;
78
+ const examScale = useRef(new Animated.Value(1)).current;
75
79
  const reviewScale = useRef(new Animated.Value(1)).current;
76
80
  const completedReviewScale = useRef(new Animated.Value(1)).current;
77
81
  const scaleAnim = useRef(new Animated.Value(1)).current;
@@ -329,31 +333,52 @@ export const ModuleCard = ({
329
333
 
330
334
  {status === 'active-dark' && (
331
335
  <View style={styles.compactDarkFooter}>
332
- <Animated.View style={{ transform: [{ scale: scheduleScale }] }}>
333
- <Pressable
334
- onPress={onSchedulePress || (() => {})}
335
- onPressIn={() => animateBtnIn(scheduleScale)}
336
- onPressOut={() => animateBtnOut(scheduleScale)}
337
- hitSlop={8}
338
- style={{ flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.primary, paddingHorizontal: scale(14), paddingVertical: scale(6), borderRadius: 100 }}
339
- >
340
- <CalendarPlus stroke={theme.colors.white} strokeWidth={2.5} size={scale(14)} />
341
- <Typography variant="label" style={{ color: theme.colors.white, fontSize: scaleText(12), fontWeight: 'bold', marginLeft: scale(6) }}>Agendar Aula</Typography>
342
- </Pressable>
343
- </Animated.View>
336
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: scale(8) }}>
337
+ {onSchedulePress && (
338
+ <Animated.View style={{ transform: [{ scale: scheduleScale }] }}>
339
+ <Pressable
340
+ onPress={onSchedulePress}
341
+ onPressIn={() => animateBtnIn(scheduleScale)}
342
+ onPressOut={() => animateBtnOut(scheduleScale)}
343
+ hitSlop={8}
344
+ style={{ flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.primary, paddingHorizontal: scale(14), paddingVertical: scale(6), borderRadius: 100 }}
345
+ >
346
+ <CalendarPlus stroke={theme.colors.white} strokeWidth={2.5} size={scale(14)} />
347
+ <Typography variant="label" style={{ color: theme.colors.white, fontSize: scaleText(12), fontWeight: 'bold', marginLeft: scale(6) }}>Agendar Aula</Typography>
348
+ </Pressable>
349
+ </Animated.View>
350
+ )}
344
351
 
345
- <Animated.View style={{ transform: [{ scale: reviewScale }] }}>
346
- <Pressable
347
- style={styles.compactReviewBtn}
348
- onPress={onReviewPress || (() => {})}
349
- onPressIn={() => animateBtnIn(reviewScale)}
350
- onPressOut={() => animateBtnOut(reviewScale)}
351
- hitSlop={8}
352
- >
353
- <RotateCcw stroke={theme.colors.primary} strokeWidth={2.5} size={scale(16)} />
354
- <Typography variant="label" style={[styles.reviewIconText, { color: theme.colors.primary, fontSize: scaleText(10), marginLeft: scale(4), marginTop: 0 }]}>REVER</Typography>
355
- </Pressable>
356
- </Animated.View>
352
+ {onExamPress && (
353
+ <Animated.View style={{ transform: [{ scale: examScale }] }}>
354
+ <Pressable
355
+ onPress={onExamPress}
356
+ onPressIn={() => animateBtnIn(examScale)}
357
+ onPressOut={() => animateBtnOut(examScale)}
358
+ hitSlop={8}
359
+ style={{ flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.primary, paddingHorizontal: scale(14), paddingVertical: scale(6), borderRadius: 100 }}
360
+ >
361
+ <PenTool stroke={theme.colors.white} strokeWidth={2.5} size={scale(14)} />
362
+ <Typography variant="label" style={{ color: theme.colors.white, fontSize: scaleText(12), fontWeight: 'bold', marginLeft: scale(6) }}>Fazer Exame</Typography>
363
+ </Pressable>
364
+ </Animated.View>
365
+ )}
366
+ </View>
367
+
368
+ {onReviewPress && (
369
+ <Animated.View style={{ transform: [{ scale: reviewScale }] }}>
370
+ <Pressable
371
+ style={styles.compactReviewBtn}
372
+ onPress={onReviewPress}
373
+ onPressIn={() => animateBtnIn(reviewScale)}
374
+ onPressOut={() => animateBtnOut(reviewScale)}
375
+ hitSlop={8}
376
+ >
377
+ <RotateCcw stroke={theme.colors.primary} strokeWidth={2.5} size={scale(16)} />
378
+ <Typography variant="label" style={[styles.reviewIconText, { color: theme.colors.primary, fontSize: scaleText(10), marginLeft: scale(4), marginTop: 0 }]}>REVER</Typography>
379
+ </Pressable>
380
+ </Animated.View>
381
+ )}
357
382
  </View>
358
383
  )}
359
384