All files / apps/chatbot/src/components/MessageList/blocks ErrorBlock.tsx

100% Statements 8/8
91.66% Branches 11/12
100% Functions 3/3
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                        2x 8x 8x     2x 8x   8x                                     8x                                                                              
import React from "react";
import { Text, TouchableOpacity, View } from "react-native";
 
import { makeStyles } from "@repo/ui/themes/makeStyles";
import { textStyles } from "@repo/ui/themes/typography";
 
import { Block } from "@/types/chat";
 
/**
 * A dropped connection is the one failure the user can act on themselves, so
 * it gets plain wording instead of the raw transport error.
 */
const isNetworkFailure = (block: Block) => {
  const haystack = `${block.text ?? ""} ${block.message ?? ""}`.toLowerCase();
  return haystack.includes("http 0:") || haystack.includes("network");
};
 
export const ErrorBlock = ({ block, onReset }: { block: Block; onReset: () => void }) => {
  const styles = useStyles();
 
  return (
    <View style={styles.blockError}>
      <View style={styles.errorHeader}>
        <Text style={styles.errorTitle}>Service Error</Text>
      </View>
 
      <Text style={styles.errorText}>
        {isNetworkFailure(block)
          ? "Oops, looks like your connection dropped. Please try again."
          : block.text || block.message}
      </Text>
 
      <TouchableOpacity style={styles.retryBtn} onPress={onReset}>
        <Text style={styles.retryText}>Reset Thread</Text>
      </TouchableOpacity>
    </View>
  );
};
 
const useStyles = makeStyles((theme) => ({
  blockError: {
    marginTop: -12,
  },
  errorHeader: {
    flexDirection: "row",
    alignItems: "center",
    gap: 8,
    marginBottom: 6,
  },
  errorTitle: {
    ...textStyles.content.semiBold,
    fontSize: 14,
    color: theme.colors.text.error,
  },
  errorText: {
    ...textStyles.content.regular,
    color: theme.colors.text.muted,
    fontSize: 13,
    lineHeight: 18,
    marginBottom: 12,
  },
  retryBtn: {
    alignItems: "center",
    justifyContent: "center",
    borderRadius: 12,
    borderWidth: 1,
    borderColor: theme.colors.text.error,
    paddingVertical: 8,
    paddingHorizontal: 16,
    backgroundColor: theme.isNewTheme ? "rgba(243, 81, 61, 0.08)" : "#FDF2F2",
    alignSelf: "flex-start",
  },
  retryText: {
    ...textStyles.content.medium,
    fontSize: 14,
    color: theme.colors.text.error,
  },
}));