1- <!doctype html>
1+ <!DOCTYPE html>
22< html lang ="fr ">
3-
43< head >
5- < meta charset ="utf-8 " />
6- < meta name ="viewport " content ="width=device-width, initial-scale=1 " />
7- < title > Test Sentiment API</ title >
8- <!-- Tailwind CSS CDN -->
9- < script src ="https://cdn.tailwindcss.com "> </ script >
4+ < meta charset ="UTF-8 ">
5+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6+ < title > Sentiment Analysis API - Test Interface</ title >
7+ < style >
8+ * { margin : 0 ; padding : 0 ; box-sizing : border-box; }
9+ body {
10+ font-family : 'Segoe UI' , Tahoma, Geneva, Verdana, sans-serif;
11+ background : linear-gradient (135deg , # 667eea 0% , # 764ba2 100% );
12+ min-height : 100vh ;
13+ padding : 20px ;
14+ }
15+ .container {
16+ max-width : 700px ;
17+ margin : 0 auto;
18+ background : white;
19+ border-radius : 15px ;
20+ box-shadow : 0 10px 30px rgba (0 , 0 , 0 , 0.2 );
21+ overflow : hidden;
22+ }
23+ .header {
24+ background : linear-gradient (135deg , # 4CAF50, # 45a049 );
25+ color : white;
26+ padding : 30px ;
27+ text-align : center;
28+ }
29+ .header h1 { font-size : 2em ; margin-bottom : 10px ; }
30+ .header p { font-size : 1.1em ; opacity : 0.9 ; }
31+ .content { padding : 30px ; }
32+ .form-group { margin-bottom : 20px ; }
33+ label { display : block; font-weight : 600 ; margin-bottom : 8px ; color : # 333 ; }
34+ textarea {
35+ width : 100% ; padding : 15px ; border : 2px solid # e1e1e1 ; border-radius : 8px ;
36+ font-size : 16px ; font-family : inherit; resize : vertical; min-height : 120px ;
37+ transition : border-color 0.3s ease;
38+ }
39+ textarea : focus {
40+ outline : none; border-color : # 4CAF50 ;
41+ box-shadow : 0 0 0 3px rgba (76 , 175 , 80 , 0.1 );
42+ }
43+ .button-group { display : flex; gap : 15px ; margin-bottom : 25px ; }
44+ button {
45+ flex : 1 ; padding : 15px 25px ; font-size : 16px ; font-weight : 600 ; border : none;
46+ border-radius : 8px ; cursor : pointer; transition : all 0.3s ease;
47+ }
48+ .btn-primary { background : linear-gradient (135deg , # 4CAF50, # 45a049 ); color : white; }
49+ .btn-primary : hover { transform : translateY (-2px ); box-shadow : 0 5px 15px rgba (76 , 175 , 80 , 0.4 ); }
50+ .btn-secondary { background : # f8f9fa ; color : # 333 ; border : 2px solid # e1e1e1 ; }
51+ .btn-secondary : hover { background : # e9ecef ; border-color : # adb5bd ; }
52+ .result { margin-top : 25px ; padding : 20px ; border-radius : 10px ; display : none; }
53+ .result .success { background : linear-gradient (135deg , # d4edda, # c3e6cb ); border-left : 5px solid # 28a745 ; }
54+ .result .error { background : linear-gradient (135deg , # f8d7da, # f1aeb5 ); border-left : 5px solid # dc3545 ; }
55+ .result h3 { margin-bottom : 15px ; color : # 333 ; }
56+ .sentiment-display { display : flex; align-items : center; gap : 15px ; margin : 20px 0 ; }
57+ .sentiment-badge { padding : 8px 16px ; border-radius : 25px ; font-weight : 600 ; font-size : 14px ; }
58+ .sentiment-positive { background : # 28a745 ; color : white; }
59+ .sentiment-negative { background : # dc3545 ; color : white; }
60+ .confidence-bar { flex : 1 ; background : # e9ecef ; border-radius : 10px ; height : 20px ; overflow : hidden; }
61+ .confidence-fill { height : 100% ; transition : width 0.5s ease; display : flex; align-items : center; justify-content : center; color : white; font-weight : 600 ; font-size : 12px ; }
62+ .confidence-positive { background : linear-gradient (90deg , # 28a745, # 20c997 ); }
63+ .confidence-negative { background : linear-gradient (90deg , # dc3545, # e74c3c ); }
64+ .json-display { background : # f8f9fa ; border : 1px solid # e9ecef ; border-radius : 8px ; padding : 20px ; margin-top : 20px ; font-family : 'Courier New' , monospace; font-size : 14px ; max-height : 300px ; overflow-y : auto; }
65+ </ style >
1066</ head >
67+ < body >
68+ < div class ="container ">
69+ < div class ="header ">
70+ < h1 > 🎯 Sentiment Analysis API</ h1 >
71+ < p > Testez l'API et analysez vos textes</ p >
72+ </ div >
1173
12- < body class ="bg-gray-100 min-h-screen flex items-center justify-center ">
13- < div class ="max-w-2xl w-full bg-white shadow-md rounded-2xl p-8 ">
14- < h1 class ="text-2xl font-bold mb-4 "> Test de l'API pour l'analyse des sentiments</ h1 >
15- < p class ="text-gray-700 mb-6 ">
16- Tapez un texte et cliquez sur < b > Analyser</ b > .
17- <!-- L'API appelle <code class="bg-gray-100 px-1 py-0.5 rounded">POST /predict</code> et affiche le JSON de réponse. -->
18- </ p >
74+ < div class ="content ">
75+ < div class ="form-group ">
76+ < label for ="textInput "> Texte à analyser :</ label >
77+ < textarea id ="textInput " placeholder ="I love this product! "> </ textarea >
78+ </ div >
79+ < div class ="button-group ">
80+ < button id ="btn " class ="btn-primary "> 🔍 Analyser</ button >
81+ < button type ="button " onclick ="clearResults() " class ="btn-secondary "> 🗑️ Effacer</ button >
82+ </ div >
1983
20- < div class ="mb-4 ">
21- < label for ="text " class ="block font-medium text-gray-800 mb-2 "> Votre texte</ label >
22- < textarea id ="text " rows ="4 " placeholder ="I love this product! "
23- class ="w-full border border-gray-300 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-500 "> </ textarea >
84+ < div id ="result " class ="result ">
85+ < h3 > Résultat de l'analyse</ h3 >
86+ < div id ="resultContent "> </ div >
87+ < div class ="json-display ">
88+ < pre id ="jsonOutput "> </ pre >
89+ </ div >
90+ </ div >
91+ </ div >
2492 </ div >
2593
26- < button id ="btn " class ="bg-blue-600 text-white px-5 py-2 rounded-lg hover:bg-blue-700 transition ">
27- Analyser
28- </ button >
94+ < script >
95+ const btn = document . getElementById ( 'btn' ) ;
96+ const textInput = document . getElementById ( 'textInput' ) ;
97+ const result = document . getElementById ( 'result' ) ;
98+ const resultContent = document . getElementById ( 'resultContent' ) ;
99+ const jsonOutput = document . getElementById ( 'jsonOutput' ) ;
29100
30- < div class ="mt-6 ">
31- < h5 class ="text-lg font-semibold "> Résultat</ h5 >
32- < pre id ="result "
33- class ="mt-2 border border-gray-300 rounded-lg bg-gray-50 p-4 text-sm text-gray-800 whitespace-pre-wrap ">
34- Résultat…
35- </ pre >
36- </ div >
37- </ div >
101+ btn . onclick = async ( ) => {
102+ const text = textInput . value . trim ( ) ;
103+ if ( ! text ) { alert ( 'Veuillez saisir un texte.' ) ; return ; }
38104
39- < script >
40- const btn = document . getElementById ( 'btn' ) ;
41- const result = document . getElementById ( 'result' ) ;
105+ result . style . display = 'none' ;
106+ resultContent . innerHTML = 'Analyse en cours...' ;
42107
43- btn . onclick = async ( ) => {
44- const text = document . getElementById ( 'text' ) . value . trim ( ) ;
45- if ( ! text ) { result . textContent = "Veuillez saisir un texte." ; return ; }
46- result . textContent = "Analyse en cours..." ;
47- try {
48- const resp = await fetch ( "/predict" , {
49- method : "POST" ,
50- headers : { "Content-Type" : "application/json" } ,
51- body : JSON . stringify ( { text } )
52- } ) ;
53- const data = await resp . json ( ) ;
54- result . textContent = JSON . stringify ( data , null , 2 ) ;
55- } catch ( e ) {
56- result . textContent = "Erreur: " + e . message ;
57- }
58- } ;
59- </ script >
60- </ body >
108+ try {
109+ const resp = await fetch ( '/predict' , {
110+ method : 'POST' ,
111+ headers : { 'Content-Type' : 'application/json' } ,
112+ body : JSON . stringify ( { text } )
113+ } ) ;
114+ const data = await resp . json ( ) ;
115+ if ( resp . ok ) {
116+ const sentimentClass = data . label === 'positive' ? 'positive' : 'negative' ;
117+ const confidencePercent = Math . round ( data . confidence * 100 ) ;
118+ resultContent . innerHTML = `
119+ <div class="sentiment-display">
120+ <span class="sentiment-badge sentiment-${ sentimentClass } ">
121+ ${ data . label === 'positive' ? '😊 POSITIF' : '😞 NÉGATIF' }
122+ </span>
123+ <div class="confidence-bar">
124+ <div class="confidence-fill confidence-${ sentimentClass } " style="width: ${ confidencePercent } %">
125+ ${ confidencePercent } %
126+ </div>
127+ </div>
128+ </div>
129+ <p><strong>Confiance :</strong> ${ data . confidence } </p>
130+ <p><strong>Texte analysé :</strong> "${ data . text } "</p>
131+ ` ;
132+ jsonOutput . textContent = JSON . stringify ( data , null , 2 ) ;
133+ result . className = 'result success' ;
134+ } else {
135+ result . className = 'result error' ;
136+ resultContent . innerHTML = `<p>❌ Erreur : ${ data . detail || 'Analyse impossible' } </p>` ;
137+ }
138+ result . style . display = 'block' ;
139+ } catch ( e ) {
140+ result . className = 'result error' ;
141+ result . style . display = 'block' ;
142+ resultContent . innerHTML = `<p>❌ Erreur de connexion à l'API</p>` ;
143+ }
144+ } ;
61145
62- </ html >
146+ function clearResults ( ) {
147+ textInput . value = '' ;
148+ result . style . display = 'none' ;
149+ textInput . focus ( ) ;
150+ }
151+ </ script >
152+ </ body >
153+ </ html >
0 commit comments