File size: 4,656 Bytes
5db3b83
fcaa899
 
 
77af7b8
 
 
fcaa899
 
 
5db3b83
fcaa899
5db3b83
fcaa899
 
 
5db3b83
 
fcaa899
 
5db3b83
fcaa899
 
24bdd7c
5db3b83
 
fcaa899
 
5db3b83
24bdd7c
 
 
 
 
 
 
5db3b83
 
 
24bdd7c
 
 
 
 
5db3b83
 
 
 
fcaa899
 
5db3b83
77af7b8
5db3b83
77af7b8
fcaa899
 
 
 
 
24bdd7c
 
 
 
 
5db3b83
 
 
 
 
 
 
 
 
 
 
 
 
fcaa899
77af7b8
fcaa899
 
77af7b8
fcaa899
5db3b83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fcaa899
77af7b8
5db3b83
fcaa899
 
5db3b83
 
 
 
fcaa899
77af7b8
 
fcaa899
 
5db3b83
24bdd7c
 
 
 
 
 
 
 
 
fcaa899
 
5db3b83
24bdd7c
 
 
 
 
 
 
5db3b83
 
 
 
 
 
77af7b8
fcaa899
 
 
 
5db3b83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fcaa899
 
 
 
 
 
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import { useState, useEffect } from "react";
import {
  Container,
  Paper,
  Button,
  Box,
  Typography,
  List,
  ListItem,
  ListItemText,
  LinearProgress,
} from "@mui/material";
import RestartAltIcon from "@mui/icons-material/RestartAlt";
import axios from "axios";

function App() {
  const [storySegments, setStorySegments] = useState([]);
  const [currentChoices, setCurrentChoices] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  const handleStoryAction = async (action, choiceId = null) => {
    setIsLoading(true);
    try {
      const response = await axios.post("http://localhost:8000/api/chat", {
        message: action,
        choice_id: choiceId,
      });

      if (action === "restart") {
        setStorySegments([
          {
            text: response.data.story_text,
            isChoice: false,
            isDeath: response.data.is_death,
          },
        ]);
      } else {
        setStorySegments((prev) => [
          ...prev,
          {
            text: response.data.story_text,
            isChoice: false,
            isDeath: response.data.is_death,
          },
        ]);
      }

      setCurrentChoices(response.data.choices);
    } catch (error) {
      console.error("Error:", error);
      setStorySegments((prev) => [
        ...prev,
        { text: "Connection lost with the storyteller...", isChoice: false },
      ]);
    } finally {
      setIsLoading(false);
    }
  };

  // Start the story when the component mounts
  useEffect(() => {
    handleStoryAction("restart");
  }, []);

  const handleChoice = async (choiceId) => {
    // Add the chosen option to the story
    setStorySegments((prev) => [
      ...prev,
      {
        text: currentChoices.find((c) => c.id === choiceId).text,
        isChoice: true,
      },
    ]);
    // Continue the story with this choice
    await handleStoryAction("choice", choiceId);
  };

  return (
    <Container maxWidth="md" sx={{ mt: 4 }}>
      <Paper
        elevation={3}
        sx={{ height: "80vh", display: "flex", flexDirection: "column", p: 2 }}
      >
        <Box
          sx={{
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
            mb: 2,
          }}
        >
          <Typography variant="h4" component="h1">
            Echoes of Influence
          </Typography>
          <Button
            variant="outlined"
            startIcon={<RestartAltIcon />}
            onClick={() => handleStoryAction("restart")}
            disabled={isLoading}
          >
            Restart
          </Button>
        </Box>

        {isLoading && <LinearProgress sx={{ mb: 2 }} />}

        <List sx={{ flexGrow: 1, overflow: "auto", mb: 2 }}>
          {storySegments.map((segment, index) => (
            <ListItem
              key={index}
              sx={{
                justifyContent: segment.isChoice ? "flex-end" : "flex-start",
                display: "flex",
              }}
            >
              <Paper
                elevation={1}
                sx={{
                  p: 2,
                  maxWidth: "80%",
                  bgcolor: segment.isDeath
                    ? "error.light"
                    : segment.isChoice
                    ? "primary.light"
                    : "grey.100",
                  color:
                    segment.isDeath || segment.isChoice
                      ? "white"
                      : "text.primary",
                }}
              >
                <ListItemText
                  primary={
                    segment.isDeath
                      ? "DEATH"
                      : segment.isChoice
                      ? "Your Choice"
                      : "Story"
                  }
                  secondary={segment.text}
                  primaryTypographyProps={{
                    variant: "subtitle2",
                    color: segment.isChoice ? "inherit" : "primary",
                  }}
                />
              </Paper>
            </ListItem>
          ))}
        </List>

        {currentChoices.length > 0 && (
          <Box sx={{ display: "flex", justifyContent: "center", gap: 2 }}>
            {currentChoices.map((choice) => (
              <Button
                key={choice.id}
                variant="contained"
                onClick={() => handleChoice(choice.id)}
                disabled={isLoading}
                sx={{ minWidth: "200px" }}
              >
                {choice.text}
              </Button>
            ))}
          </Box>
        )}
      </Paper>
    </Container>
  );
}

export default App;