Skip to main content

Overview

The IncidentCard component renders a touchable card displaying incident details including title, description, priority level, status, area, and creation date. It supports both employee and guest views with customizable navigation.

Features

  • Displays incident title, description (truncated to 2 lines)
  • Color-coded priority badges (baja, media, alta, urgente)
  • Status indicators with dot and label
  • Area/department badges
  • Formatted timestamps
  • Optional press handling and disabled state
  • Automatic routing based on user role

Usage

Basic Usage

import { IncidentCard } from '@/components/IncidentCard'

export default function IncidentsList() {
  const incident = {
    id: '123',
    title: 'Aire acondicionado no enfría',
    description: 'El aire de la habitación 302 no está enfriando...',
    priority: 'alta',
    status: 'en_progreso',
    created_at: '2024-03-05T10:30:00Z',
    areas: {
      name: 'mantenimiento'
    }
  }

  return <IncidentCard incident={incident} />
}

Custom Press Handler

<IncidentCard
  incident={incident}
  onPress={() => {
    console.log('Card pressed:', incident.id)
    // Custom navigation logic
  }}
/>

Disabled State

<IncidentCard
  incident={incident}
  disabled={true}
/>

Props

incident
Incident
required
The incident object containing all display information
onPress
() => void
Optional callback function when the card is pressed. If not provided, defaults to navigating to the incident detail page based on user role (employee or guest)
disabled
boolean
default:"false"
When true, the card is not touchable and displays as a static view

Types

Incident

type Incident = {
  id: string
  title: string
  description: string
  priority: "baja" | "media" | "alta"
  status: string
  created_at: string
  areas: {
    name: string
  }
}
id
string
Unique identifier for the incident
title
string
The incident title displayed at the top of the card
description
string
Full description of the incident (truncated to 2 lines in display)
priority
'baja' | 'media' | 'alta'
Priority level determining badge color
status
string
Current status (pendiente, recibida, en_progreso, resuelta)
created_at
string
ISO 8601 timestamp of when the incident was created
areas
{ name: string }
Associated area/department object

Priority Configuration

Priorities are displayed with color-coded badges:
const priorityConfig = {
  baja: { label: "Baja", color: "#10B981", bgColor: "#ECFDF5" },
  media: { label: "Media", color: "#F59E0B", bgColor: "#FEF3C7" },
  alta: { label: "Alta", color: "#EF4444", bgColor: "#FEE2E2" },
  urgente: { label: "Urgente", color: "#ff0000", bgColor: "#ff9595" },
}
  • baja: Green badge (#10B981)
  • media: Orange badge (#F59E0B)
  • alta: Red badge (#EF4444)
  • urgente: Bright red badge (#ff0000)

Status Configuration

Status badges display with a colored dot and label:
const statusConfig = {
  pendiente: { label: "Pendiente", color: "#6b72801c", textColor: "#6b7280da" },
  recibida: { label: "Recibida", color: "#FEF3C7", textColor: "#F59E0B" },
  en_progreso: { label: "En Progreso", color: "#3b83f61a", textColor: "#3b83f6cd" },
  resuelta: { label: "Resuelta", color: "#10b98119", textColor: "#10b981c3" },
}
  • pendiente: Gray indicator
  • recibida: Orange indicator
  • en_progreso: Blue indicator
  • resuelta: Green indicator

Card Structure

The card is organized into three main sections:
<View style={styles.cardHeader}>
  <AppText style={styles.cardTitle}>{incident.title}</AppText>
  <View style={styles.badges}>
    {/* Priority badge */}
  </View>
</View>

Body

<AppText style={styles.description} numberOfLines={2}>
  {incident.description}
</AppText>
<View style={styles.cardFooter}>
  <View style={styles.badgesRow}>
    {/* Status badge */}
    {/* Area badge */}
  </View>
  <AppText style={styles.date}>
    {formatDateTime(incident.created_at)}
  </AppText>
</View>
The component includes two versions with different default navigation:

Employee Version

Located in mobile/components/IncidentCard.tsx:
router.push(`/(empleado)/incidents/${incident.id}`)

Guest Version

Located in mobile/components/MyIncidentsCard.tsx:
router.push(`/(guest)/incidents/${incident.id}`)

Dependencies

  • @/components/AppText - Custom text component
  • @/hooks/use-date-format - Date formatting hook
  • expo-router - Navigation
  • react-native - Core UI components

Hooks Used

useDateFormat

const { formatDateTime } = useDateFormat()
Formats ISO date strings into localized, readable timestamps.

Styling

The card has the following visual characteristics:
  • White background with rounded corners (14px radius)
  • Subtle shadow (elevation: 2)
  • 12px padding
  • 10px gap between sections
  • Border at footer top (#F1F5F9)

Complete Example

import { IncidentCard, type Incident } from '@/components/IncidentCard'
import { FlatList, StyleSheet, View } from 'react-native'

const incidents: Incident[] = [
  {
    id: '1',
    title: 'Aire no enfría',
    description: 'El aire acondicionado de la habitación 302 no está funcionando',
    priority: 'alta',
    status: 'en_progreso',
    created_at: '2024-03-05T10:30:00Z',
    areas: { name: 'mantenimiento' }
  },
  {
    id: '2',
    title: 'Bombilla fundida',
    description: 'Se necesita reemplazar la bombilla del baño',
    priority: 'baja',
    status: 'pendiente',
    created_at: '2024-03-05T11:15:00Z',
    areas: { name: 'mantenimiento' }
  },
]

export default function IncidentsList() {
  return (
    <FlatList
      data={incidents}
      renderItem={({ item }) => <IncidentCard incident={item} />}
      keyExtractor={(item) => item.id}
      contentContainerStyle={styles.list}
    />
  )
}

const styles = StyleSheet.create({
  list: {
    padding: 16,
    gap: 12,
  },
})

Accessibility

  • Touchable opacity provides visual feedback (0.7)
  • Text truncation prevents layout breaking
  • Sufficient color contrast for all badges
  • Touch target meets minimum size requirements
  • Status indicators use both color and text labels

Build docs developers (and LLMs) love