|
|
<!DOCTYPE html> |
|
|
<html lang="en" dir="ltr"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<title>ContinuousImprovement Pro - Advanced PDCA Methodology</title> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
|
|
<style> |
|
|
:root { |
|
|
--primary: #1e40af; |
|
|
--secondary: #3b82f6; |
|
|
--accent: #60a5fa; |
|
|
--background: #f8fafc; |
|
|
--surface: #ffffff; |
|
|
--text: #1e293b; |
|
|
--text-secondary: #64748b; |
|
|
--border: #e2e8f0; |
|
|
--success: #10b981; |
|
|
--warning: #f59e0b; |
|
|
--error: #ef4444; |
|
|
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); |
|
|
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); |
|
|
} |
|
|
|
|
|
* { |
|
|
box-sizing: border-box; |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
} |
|
|
|
|
|
body { |
|
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
|
|
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%); |
|
|
color: var(--text); |
|
|
line-height: 1.6; |
|
|
min-height: 100vh; |
|
|
padding: 15px; |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
|
|
|
|
|
|
[dir="rtl"] { |
|
|
text-align: right; |
|
|
} |
|
|
|
|
|
[dir="rtl"] .container { |
|
|
direction: rtl; |
|
|
} |
|
|
|
|
|
[dir="rtl"] .api-key-section { |
|
|
margin: 15px 15px 15px auto; |
|
|
} |
|
|
|
|
|
[dir="rtl"] .pdca-steps { |
|
|
direction: rtl; |
|
|
} |
|
|
|
|
|
[dir="rtl"] .generate-btn { |
|
|
direction: rtl; |
|
|
} |
|
|
|
|
|
|
|
|
.language-landing { |
|
|
display: block; |
|
|
max-width: 600px; |
|
|
margin: 50px auto; |
|
|
background: var(--surface); |
|
|
border-radius: 16px; |
|
|
box-shadow: var(--shadow-lg); |
|
|
padding: 40px; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.language-landing h1 { |
|
|
font-size: 2.5rem; |
|
|
font-weight: 800; |
|
|
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
background-clip: text; |
|
|
margin-bottom: 15px; |
|
|
} |
|
|
|
|
|
.language-landing p { |
|
|
font-size: 1.1rem; |
|
|
color: var(--text-secondary); |
|
|
margin-bottom: 30px; |
|
|
} |
|
|
|
|
|
.language-selector { |
|
|
margin-bottom: 25px; |
|
|
} |
|
|
|
|
|
.language-selector label { |
|
|
display: block; |
|
|
margin-bottom: 10px; |
|
|
font-weight: 600; |
|
|
color: var(--text); |
|
|
font-size: 1.1rem; |
|
|
} |
|
|
|
|
|
.language-selector select { |
|
|
width: 100%; |
|
|
padding: 15px 20px; |
|
|
border: 2px solid var(--border); |
|
|
border-radius: 12px; |
|
|
font-size: 1.1rem; |
|
|
font-family: inherit; |
|
|
background: var(--surface); |
|
|
transition: all 0.2s ease; |
|
|
margin-bottom: 20px; |
|
|
} |
|
|
|
|
|
.language-selector select:focus { |
|
|
outline: none; |
|
|
border-color: var(--primary); |
|
|
box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.1); |
|
|
} |
|
|
|
|
|
.api-key-landing { |
|
|
margin-bottom: 25px; |
|
|
} |
|
|
|
|
|
.api-key-landing label { |
|
|
display: block; |
|
|
margin-bottom: 10px; |
|
|
font-weight: 600; |
|
|
color: var(--text); |
|
|
font-size: 1.1rem; |
|
|
} |
|
|
|
|
|
.api-key-landing input { |
|
|
width: 100%; |
|
|
padding: 15px 20px; |
|
|
border: 2px solid var(--border); |
|
|
border-radius: 12px; |
|
|
font-size: 1.1rem; |
|
|
background: var(--surface); |
|
|
transition: all 0.2s ease; |
|
|
font-family: 'Courier New', monospace; |
|
|
} |
|
|
|
|
|
.api-key-landing input:focus { |
|
|
outline: none; |
|
|
border-color: var(--primary); |
|
|
box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.1); |
|
|
} |
|
|
|
|
|
.start-btn { |
|
|
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); |
|
|
color: white; |
|
|
padding: 18px 40px; |
|
|
border: none; |
|
|
border-radius: 12px; |
|
|
font-size: 1.2rem; |
|
|
font-weight: 700; |
|
|
cursor: pointer; |
|
|
transition: all 0.3s ease; |
|
|
width: 100%; |
|
|
} |
|
|
|
|
|
.start-btn:hover { |
|
|
transform: translateY(-2px); |
|
|
box-shadow: 0 12px 24px -8px rgba(30, 64, 175, 0.4); |
|
|
} |
|
|
|
|
|
.start-btn:disabled { |
|
|
opacity: 0.7; |
|
|
cursor: not-allowed; |
|
|
transform: none; |
|
|
} |
|
|
|
|
|
|
|
|
.cache-management { |
|
|
background: rgba(30, 64, 175, 0.05); |
|
|
border: 1px solid rgba(30, 64, 175, 0.1); |
|
|
border-radius: 12px; |
|
|
padding: 20px; |
|
|
margin-bottom: 25px; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.cache-management h3 { |
|
|
color: var(--primary); |
|
|
margin-bottom: 15px; |
|
|
font-size: 1.1rem; |
|
|
font-weight: 600; |
|
|
} |
|
|
|
|
|
.cache-status-display { |
|
|
background: rgba(16, 185, 129, 0.1); |
|
|
border: 1px solid rgba(16, 185, 129, 0.2); |
|
|
color: var(--success); |
|
|
padding: 12px 16px; |
|
|
border-radius: 8px; |
|
|
margin-bottom: 15px; |
|
|
font-size: 0.9rem; |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.cache-status-display.no-cache { |
|
|
background: rgba(100, 116, 139, 0.1); |
|
|
border-color: rgba(100, 116, 139, 0.2); |
|
|
color: var(--text-secondary); |
|
|
} |
|
|
|
|
|
.clear-cache-btn { |
|
|
background: linear-gradient(135deg, var(--warning) 0%, #f59e0b 100%); |
|
|
color: white; |
|
|
padding: 12px 24px; |
|
|
border: none; |
|
|
border-radius: 8px; |
|
|
font-size: 0.9rem; |
|
|
font-weight: 600; |
|
|
cursor: pointer; |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
|
|
|
.clear-cache-btn:hover { |
|
|
transform: translateY(-1px); |
|
|
box-shadow: 0 6px 12px -4px rgba(245, 158, 11, 0.4); |
|
|
} |
|
|
|
|
|
.clear-cache-btn:disabled { |
|
|
opacity: 0.5; |
|
|
cursor: not-allowed; |
|
|
transform: none; |
|
|
} |
|
|
|
|
|
|
|
|
.cache-status { |
|
|
background: rgba(16, 185, 129, 0.1); |
|
|
border: 1px solid rgba(16, 185, 129, 0.2); |
|
|
color: var(--success); |
|
|
padding: 8px 12px; |
|
|
border-radius: 6px; |
|
|
margin-bottom: 15px; |
|
|
font-size: 0.85rem; |
|
|
text-align: center; |
|
|
font-weight: 500; |
|
|
display: none; |
|
|
} |
|
|
|
|
|
.cache-status.cached { |
|
|
display: block; |
|
|
} |
|
|
|
|
|
.cache-status.translating { |
|
|
background: rgba(30, 64, 175, 0.1); |
|
|
border-color: rgba(30, 64, 175, 0.2); |
|
|
color: var(--primary); |
|
|
} |
|
|
|
|
|
|
|
|
.translation-overlay { |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
background: rgba(30, 64, 175, 0.9); |
|
|
display: none; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
z-index: 10000; |
|
|
color: white; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.translation-content { |
|
|
background: rgba(255, 255, 255, 0.1); |
|
|
padding: 40px; |
|
|
border-radius: 16px; |
|
|
backdrop-filter: blur(10px); |
|
|
} |
|
|
|
|
|
.translation-spinner { |
|
|
width: 50px; |
|
|
height: 50px; |
|
|
border: 4px solid rgba(255, 255, 255, 0.3); |
|
|
border-radius: 50%; |
|
|
border-top-color: white; |
|
|
animation: spin 1s ease-in-out infinite; |
|
|
margin: 0 auto 20px; |
|
|
} |
|
|
|
|
|
|
|
|
.main-app { |
|
|
display: none; |
|
|
} |
|
|
|
|
|
.container { |
|
|
max-width: 1000px; |
|
|
margin: 0 auto; |
|
|
background: var(--surface); |
|
|
border-radius: 16px; |
|
|
box-shadow: var(--shadow-lg); |
|
|
overflow: hidden; |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
|
|
|
.api-key-section { |
|
|
background: rgba(30, 64, 175, 0.05); |
|
|
border: 1px solid rgba(30, 64, 175, 0.1); |
|
|
border-radius: 8px; |
|
|
padding: 12px; |
|
|
margin: 15px; |
|
|
max-width: 280px; |
|
|
} |
|
|
|
|
|
.api-key-section label { |
|
|
font-size: 12px; |
|
|
font-weight: 600; |
|
|
color: var(--primary); |
|
|
margin-bottom: 6px; |
|
|
display: block; |
|
|
} |
|
|
|
|
|
.api-key-section input { |
|
|
width: 100%; |
|
|
padding: 8px 12px; |
|
|
border: 1px solid var(--border); |
|
|
border-radius: 6px; |
|
|
font-size: 14px; |
|
|
background: var(--surface); |
|
|
transition: all 0.2s ease; |
|
|
font-family: 'Courier New', monospace; |
|
|
} |
|
|
|
|
|
.api-key-section input:focus { |
|
|
outline: none; |
|
|
border-color: var(--primary); |
|
|
box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.1); |
|
|
} |
|
|
|
|
|
|
|
|
.language-switcher { |
|
|
position: absolute; |
|
|
top: 15px; |
|
|
right: 15px; |
|
|
display: flex; |
|
|
gap: 10px; |
|
|
align-items: center; |
|
|
} |
|
|
|
|
|
[dir="rtl"] .language-switcher { |
|
|
right: auto; |
|
|
left: 15px; |
|
|
} |
|
|
|
|
|
.language-switch-btn { |
|
|
background: rgba(30, 64, 175, 0.05); |
|
|
border: 1px solid rgba(30, 64, 175, 0.1); |
|
|
border-radius: 8px; |
|
|
padding: 8px 12px; |
|
|
font-size: 12px; |
|
|
cursor: pointer; |
|
|
transition: all 0.2s ease; |
|
|
color: var(--primary); |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.language-switch-btn:hover { |
|
|
background: rgba(30, 64, 175, 0.1); |
|
|
} |
|
|
|
|
|
.mini-clear-cache { |
|
|
background: rgba(245, 158, 11, 0.1); |
|
|
border: 1px solid rgba(245, 158, 11, 0.2); |
|
|
color: var(--warning); |
|
|
padding: 6px 10px; |
|
|
border-radius: 6px; |
|
|
font-size: 11px; |
|
|
cursor: pointer; |
|
|
transition: all 0.2s ease; |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.mini-clear-cache:hover { |
|
|
background: rgba(245, 158, 11, 0.2); |
|
|
} |
|
|
|
|
|
|
|
|
.main-content { |
|
|
padding: 20px 30px 30px; |
|
|
} |
|
|
|
|
|
|
|
|
.header { |
|
|
text-align: center; |
|
|
margin-bottom: 25px; |
|
|
padding-bottom: 20px; |
|
|
border-bottom: 2px solid var(--border); |
|
|
} |
|
|
|
|
|
.header h1 { |
|
|
font-size: 2.5rem; |
|
|
font-weight: 800; |
|
|
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
background-clip: text; |
|
|
margin-bottom: 8px; |
|
|
} |
|
|
|
|
|
.header .subtitle { |
|
|
font-size: 1.1rem; |
|
|
color: var(--text-secondary); |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.header .description { |
|
|
font-size: 1rem; |
|
|
color: var(--text-secondary); |
|
|
margin-top: 12px; |
|
|
max-width: 600px; |
|
|
margin-left: auto; |
|
|
margin-right: auto; |
|
|
} |
|
|
|
|
|
|
|
|
.pdca-steps { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
|
|
gap: 15px; |
|
|
margin-bottom: 25px; |
|
|
} |
|
|
|
|
|
.step-card { |
|
|
background: rgba(30, 64, 175, 0.05); |
|
|
border: 1px solid rgba(30, 64, 175, 0.1); |
|
|
border-radius: 8px; |
|
|
padding: 15px; |
|
|
text-align: center; |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.step-card.plan { |
|
|
background: rgba(239, 68, 68, 0.05); |
|
|
border-color: rgba(239, 68, 68, 0.1); |
|
|
} |
|
|
|
|
|
.step-card.do { |
|
|
background: rgba(245, 158, 11, 0.05); |
|
|
border-color: rgba(245, 158, 11, 0.1); |
|
|
} |
|
|
|
|
|
.step-card.check { |
|
|
background: rgba(16, 185, 129, 0.05); |
|
|
border-color: rgba(16, 185, 129, 0.1); |
|
|
} |
|
|
|
|
|
.step-card.act { |
|
|
background: rgba(30, 64, 175, 0.05); |
|
|
border-color: rgba(30, 64, 175, 0.1); |
|
|
} |
|
|
|
|
|
.step-card h4 { |
|
|
color: var(--primary); |
|
|
font-size: 0.9rem; |
|
|
font-weight: 600; |
|
|
margin-bottom: 6px; |
|
|
} |
|
|
|
|
|
.step-card.plan h4 { color: #ef4444; } |
|
|
.step-card.do h4 { color: #f59e0b; } |
|
|
.step-card.check h4 { color: #10b981; } |
|
|
.step-card.act h4 { color: #1e40af; } |
|
|
|
|
|
.step-card p { |
|
|
font-size: 0.8rem; |
|
|
color: var(--text-secondary); |
|
|
} |
|
|
|
|
|
|
|
|
.input-section { |
|
|
background: var(--surface); |
|
|
border: 1px solid var(--border); |
|
|
border-radius: 12px; |
|
|
padding: 20px; |
|
|
margin-bottom: 25px; |
|
|
transition: all 0.3s ease; |
|
|
box-shadow: var(--shadow); |
|
|
} |
|
|
|
|
|
.input-section:hover { |
|
|
border-color: var(--primary); |
|
|
box-shadow: 0 8px 25px -8px rgba(30, 64, 175, 0.3); |
|
|
} |
|
|
|
|
|
.input-section h3 { |
|
|
font-size: 1.1rem; |
|
|
font-weight: 700; |
|
|
color: var(--primary); |
|
|
margin-bottom: 8px; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 8px; |
|
|
} |
|
|
|
|
|
.input-section .description { |
|
|
font-size: 0.9rem; |
|
|
color: var(--text-secondary); |
|
|
margin-bottom: 12px; |
|
|
} |
|
|
|
|
|
|
|
|
label { |
|
|
display: block; |
|
|
margin-bottom: 6px; |
|
|
font-weight: 600; |
|
|
color: var(--text); |
|
|
font-size: 0.95rem; |
|
|
} |
|
|
|
|
|
textarea { |
|
|
width: 100%; |
|
|
padding: 12px 16px; |
|
|
border: 2px solid var(--border); |
|
|
border-radius: 8px; |
|
|
font-size: 1rem; |
|
|
font-family: inherit; |
|
|
background: var(--surface); |
|
|
transition: all 0.2s ease; |
|
|
resize: vertical; |
|
|
min-height: 150px; |
|
|
} |
|
|
|
|
|
textarea:focus { |
|
|
outline: none; |
|
|
border-color: var(--primary); |
|
|
box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.1); |
|
|
} |
|
|
|
|
|
|
|
|
.char-counter { |
|
|
font-size: 0.8rem; |
|
|
color: var(--text-secondary); |
|
|
text-align: right; |
|
|
margin-top: 4px; |
|
|
} |
|
|
|
|
|
[dir="rtl"] .char-counter { |
|
|
text-align: left; |
|
|
} |
|
|
|
|
|
|
|
|
.generate-btn { |
|
|
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); |
|
|
color: white; |
|
|
padding: 16px 32px; |
|
|
border: none; |
|
|
border-radius: 12px; |
|
|
font-size: 1.1rem; |
|
|
font-weight: 700; |
|
|
cursor: pointer; |
|
|
transition: all 0.3s ease; |
|
|
display: block; |
|
|
margin: 25px auto; |
|
|
min-width: 280px; |
|
|
position: relative; |
|
|
overflow: hidden; |
|
|
} |
|
|
|
|
|
.generate-btn:hover { |
|
|
transform: translateY(-2px); |
|
|
box-shadow: 0 12px 24px -8px rgba(30, 64, 175, 0.4); |
|
|
} |
|
|
|
|
|
.generate-btn:active { |
|
|
transform: translateY(0); |
|
|
} |
|
|
|
|
|
.generate-btn:disabled { |
|
|
opacity: 0.7; |
|
|
cursor: not-allowed; |
|
|
transform: none; |
|
|
} |
|
|
|
|
|
|
|
|
.spinner { |
|
|
display: none; |
|
|
width: 20px; |
|
|
height: 20px; |
|
|
border: 2px solid rgba(255, 255, 255, 0.3); |
|
|
border-radius: 50%; |
|
|
border-top-color: white; |
|
|
animation: spin 1s ease-in-out infinite; |
|
|
margin-right: 8px; |
|
|
} |
|
|
|
|
|
[dir="rtl"] .spinner { |
|
|
margin-right: 0; |
|
|
margin-left: 8px; |
|
|
} |
|
|
|
|
|
@keyframes spin { |
|
|
to { transform: rotate(360deg); } |
|
|
} |
|
|
|
|
|
|
|
|
.output-section { |
|
|
margin-top: 30px; |
|
|
} |
|
|
|
|
|
.output-section h2 { |
|
|
font-size: 1.5rem; |
|
|
font-weight: 700; |
|
|
color: var(--primary); |
|
|
margin-bottom: 15px; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 8px; |
|
|
} |
|
|
|
|
|
.output-area { |
|
|
background: var(--surface); |
|
|
border: 2px solid var(--border); |
|
|
border-radius: 12px; |
|
|
padding: 20px; |
|
|
min-height: 300px; |
|
|
transition: all 0.3s ease; |
|
|
position: relative; |
|
|
overflow-x: auto; |
|
|
} |
|
|
|
|
|
.output-area:empty::before { |
|
|
content: "Your comprehensive PDCA cycle explanation will appear here..."; |
|
|
color: var(--text-secondary); |
|
|
font-style: italic; |
|
|
} |
|
|
|
|
|
|
|
|
.output-area h3 { |
|
|
color: var(--primary); |
|
|
border-bottom: 2px solid var(--primary); |
|
|
padding-bottom: 8px; |
|
|
margin: 20px 0 15px 0; |
|
|
font-size: 1.2rem; |
|
|
} |
|
|
|
|
|
.output-area h4 { |
|
|
color: var(--secondary); |
|
|
margin: 15px 0 10px 0; |
|
|
font-size: 1.1rem; |
|
|
} |
|
|
|
|
|
.output-area ul { |
|
|
margin: 10px 0 15px 20px; |
|
|
line-height: 1.7; |
|
|
} |
|
|
|
|
|
.output-area li { |
|
|
margin-bottom: 5px; |
|
|
} |
|
|
|
|
|
.output-area p { |
|
|
margin: 12px 0; |
|
|
line-height: 1.7; |
|
|
} |
|
|
|
|
|
.output-area strong { |
|
|
color: var(--primary); |
|
|
} |
|
|
|
|
|
|
|
|
.error-message { |
|
|
background: rgba(239, 68, 68, 0.1); |
|
|
border: 1px solid rgba(239, 68, 68, 0.2); |
|
|
color: var(--error); |
|
|
padding: 12px 16px; |
|
|
border-radius: 8px; |
|
|
margin: 10px 0; |
|
|
font-size: 0.9rem; |
|
|
display: none; |
|
|
} |
|
|
|
|
|
|
|
|
.footer { |
|
|
text-align: center; |
|
|
padding: 20px; |
|
|
background: rgba(30, 64, 175, 0.05); |
|
|
border-top: 1px solid var(--border); |
|
|
color: var(--text-secondary); |
|
|
font-size: 0.9rem; |
|
|
} |
|
|
|
|
|
|
|
|
@media (max-width: 768px) { |
|
|
body { |
|
|
padding: 10px; |
|
|
} |
|
|
|
|
|
.language-landing { |
|
|
margin: 20px auto; |
|
|
padding: 30px 20px; |
|
|
} |
|
|
|
|
|
.api-key-section { |
|
|
margin: 10px; |
|
|
max-width: none; |
|
|
} |
|
|
|
|
|
.language-switcher { |
|
|
position: relative; |
|
|
top: auto; |
|
|
right: auto; |
|
|
margin-bottom: 15px; |
|
|
justify-content: center; |
|
|
} |
|
|
|
|
|
.main-content { |
|
|
padding: 15px 20px 20px; |
|
|
} |
|
|
|
|
|
.header h1 { |
|
|
font-size: 2rem; |
|
|
} |
|
|
|
|
|
.input-section { |
|
|
padding: 15px; |
|
|
} |
|
|
|
|
|
.pdca-steps { |
|
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); |
|
|
} |
|
|
|
|
|
.generate-btn { |
|
|
width: 100%; |
|
|
margin: 20px 0; |
|
|
} |
|
|
|
|
|
.output-area { |
|
|
padding: 15px; |
|
|
} |
|
|
} |
|
|
|
|
|
@media (max-width: 480px) { |
|
|
.language-landing h1 { |
|
|
font-size: 2rem; |
|
|
} |
|
|
|
|
|
.header h1 { |
|
|
font-size: 1.8rem; |
|
|
} |
|
|
|
|
|
.input-section { |
|
|
padding: 12px; |
|
|
} |
|
|
|
|
|
.pdca-steps { |
|
|
grid-template-columns: 1fr 1fr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@media (prefers-color-scheme: dark) { |
|
|
:root { |
|
|
--background: #0f172a; |
|
|
--surface: #1e293b; |
|
|
--text: #f1f5f9; |
|
|
--text-secondary: #94a3b8; |
|
|
--border: #334155; |
|
|
} |
|
|
|
|
|
body { |
|
|
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); |
|
|
} |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
|
|
|
<div class="translation-overlay" id="translationOverlay"> |
|
|
<div class="translation-content"> |
|
|
<div class="translation-spinner"></div> |
|
|
<h2 id="translationTitle">Translating Interface...</h2> |
|
|
<p id="translationMessage">Please wait while we translate the interface to your selected language.</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="language-landing" id="languageLanding"> |
|
|
<h1 data-translate="app_title">ContinuousImprovement Pro</h1> |
|
|
<p data-translate="welcome_message">Welcome! Please select your preferred language and enter your API key to get started.</p> |
|
|
|
|
|
|
|
|
<div class="cache-status" id="cacheStatus"> |
|
|
💾 Translations cached - instant loading! |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="cache-management" id="cacheManagement"> |
|
|
<h3 data-translate="cache_management_title">🗂️ Translation Cache Management</h3> |
|
|
<div class="cache-status-display" id="cacheStatusDisplay"> |
|
|
<span data-translate="cache_status_checking">Checking cache status...</span> |
|
|
</div> |
|
|
<button class="clear-cache-btn" id="clearCacheBtn" data-translate="clear_cache_button"> |
|
|
🗑️ Clear All Cached Translations |
|
|
</button> |
|
|
</div> |
|
|
|
|
|
<div class="language-selector"> |
|
|
<label for="languageSelect" data-translate="select_language">🌐 Select Language</label> |
|
|
<select id="languageSelect"> |
|
|
<option value="en">🇺🇸 English</option> |
|
|
<option value="es">🇪🇸 Español (Spanish)</option> |
|
|
<option value="fr">🇫🇷 Français (French)</option> |
|
|
<option value="de">🇩🇪 Deutsch (German)</option> |
|
|
<option value="zh">🇨🇳 中文 (Chinese)</option> |
|
|
<option value="ja">🇯🇵 日本語 (Japanese)</option> |
|
|
<option value="ko">🇰🇷 한국어 (Korean)</option> |
|
|
<option value="pt">🇵🇹 Português (Portuguese)</option> |
|
|
<option value="it">🇮🇹 Italiano (Italian)</option> |
|
|
<option value="ar">🇸🇦 العربية (Arabic)</option> |
|
|
<option value="ru">🇷🇺 Русский (Russian)</option> |
|
|
<option value="hi">🇮🇳 हिन्दी (Hindi)</option> |
|
|
<option value="bn">🇧🇩 বাংলা (Bengali)</option> |
|
|
<option value="ur">🇵🇰 اردو (Urdu)</option> |
|
|
<option value="tr">🇹🇷 Türkçe (Turkish)</option> |
|
|
<option value="pl">🇵🇱 Polski (Polish)</option> |
|
|
<option value="nl">🇳🇱 Nederlands (Dutch)</option> |
|
|
<option value="sv">🇸🇪 Svenska (Swedish)</option> |
|
|
<option value="da">🇩🇰 Dansk (Danish)</option> |
|
|
<option value="no">🇳🇴 Norsk (Norwegian)</option> |
|
|
<option value="fi">🇫🇮 Suomi (Finnish)</option> |
|
|
<option value="is">🇮🇸 Íslenska (Icelandic)</option> |
|
|
<option value="cs">🇨🇿 Čeština (Czech)</option> |
|
|
<option value="sk">🇸🇰 Slovenčina (Slovak)</option> |
|
|
<option value="hu">🇭🇺 Magyar (Hungarian)</option> |
|
|
<option value="ro">🇷🇴 Română (Romanian)</option> |
|
|
<option value="bg">🇧🇬 Български (Bulgarian)</option> |
|
|
<option value="hr">🇭🇷 Hrvatski (Croatian)</option> |
|
|
<option value="sr">🇷🇸 Српски (Serbian)</option> |
|
|
<option value="sl">🇸🇮 Slovenščina (Slovenian)</option> |
|
|
<option value="mk">🇲🇰 Македонски (Macedonian)</option> |
|
|
<option value="sq">🇦🇱 Shqip (Albanian)</option> |
|
|
<option value="lv">🇱🇻 Latviešu (Latvian)</option> |
|
|
<option value="lt">🇱🇹 Lietuvių (Lithuanian)</option> |
|
|
<option value="et">🇪🇪 Eesti (Estonian)</option> |
|
|
<option value="mt">🇲🇹 Malti (Maltese)</option> |
|
|
<option value="ga">🇮🇪 Gaeilge (Irish)</option> |
|
|
<option value="cy">🏴 Cymraeg (Welsh)</option> |
|
|
<option value="eu">🏴 Euskera (Basque)</option> |
|
|
<option value="ca">🏴 Català (Catalan)</option> |
|
|
<option value="gl">🏴 Galego (Galician)</option> |
|
|
<option value="el">🇬🇷 Ελληνικά (Greek)</option> |
|
|
<option value="he">🇮🇱 עברית (Hebrew)</option> |
|
|
<option value="fa">🇮🇷 فارسی (Persian)</option> |
|
|
<option value="ps">🇦🇫 پښتو (Pashto)</option> |
|
|
<option value="ku">🏴 کوردی (Kurdish)</option> |
|
|
<option value="az">🇦🇿 Azərbaycan (Azerbaijani)</option> |
|
|
<option value="kk">🇰🇿 Қазақша (Kazakh)</option> |
|
|
<option value="ky">🇰🇬 Кыргызча (Kyrgyz)</option> |
|
|
<option value="uz">🇺🇿 O'zbek (Uzbek)</option> |
|
|
<option value="tk">🇹🇲 Türkmen (Turkmen)</option> |
|
|
<option value="tg">🇹🇯 Тоҷикӣ (Tajik)</option> |
|
|
<option value="mn">🇲🇳 Монгол (Mongolian)</option> |
|
|
<option value="ka">🇬🇪 ქართული (Georgian)</option> |
|
|
<option value="hy">🇦🇲 Հայերեն (Armenian)</option> |
|
|
<option value="th">🇹🇭 ไทย (Thai)</option> |
|
|
<option value="vi">🇻🇳 Tiếng Việt (Vietnamese)</option> |
|
|
<option value="lo">🇱🇦 ລາວ (Lao)</option> |
|
|
<option value="km">🇰🇭 ខ្មែរ (Khmer)</option> |
|
|
<option value="my">🇲🇲 မြန်မာ (Myanmar)</option> |
|
|
<option value="si">🇱🇰 සිංහල (Sinhala)</option> |
|
|
<option value="ta">🇱🇰 தமிழ் (Tamil)</option> |
|
|
<option value="te">🇮🇳 తెలుగు (Telugu)</option> |
|
|
<option value="kn">🇮🇳 ಕನ್ನಡ (Kannada)</option> |
|
|
<option value="ml">🇮🇳 മലയാളം (Malayalam)</option> |
|
|
<option value="gu">🇮🇳 ગુજરાતી (Gujarati)</option> |
|
|
<option value="pa">🇮🇳 ਪੰਜਾਬੀ (Punjabi)</option> |
|
|
<option value="or">🇮🇳 ଓଡ଼ିଆ (Odia)</option> |
|
|
<option value="as">🇮🇳 অসমীয়া (Assamese)</option> |
|
|
<option value="ne">🇳🇵 नेपाली (Nepali)</option> |
|
|
<option value="dz">🇧🇹 རྫོང་ཁ (Dzongkha)</option> |
|
|
<option value="bo">🏔️ བོད་ཡིག (Tibetan)</option> |
|
|
<option value="id">🇮🇩 Bahasa Indonesia</option> |
|
|
<option value="ms">🇲🇾 Bahasa Melayu (Malay)</option> |
|
|
<option value="tl">🇵🇭 Filipino (Tagalog)</option> |
|
|
<option value="ceb">🇵🇭 Cebuano</option> |
|
|
<option value="haw">🏝️ ʻŌlelo Hawaiʻi (Hawaiian)</option> |
|
|
<option value="mi">🇳🇿 Te Reo Māori (Maori)</option> |
|
|
<option value="sm">🇼🇸 Gagana Samoa (Samoan)</option> |
|
|
<option value="to">🇹🇴 Lea Fakatonga (Tongan)</option> |
|
|
<option value="fj">🇫🇯 Na Vosa Vakaviti (Fijian)</option> |
|
|
<option value="mg">🇲🇬 Malagasy</option> |
|
|
<option value="sw">🇰🇪 Kiswahili (Swahili)</option> |
|
|
<option value="zu">🇿🇦 isiZulu (Zulu)</option> |
|
|
<option value="xh">🇿🇦 isiXhosa (Xhosa)</option> |
|
|
<option value="af">🇿🇦 Afrikaans</option> |
|
|
<option value="st">🇱🇸 Sesotho (Southern Sotho)</option> |
|
|
<option value="tn">🇧🇼 Setswana (Tswana)</option> |
|
|
<option value="ss">🇸🇿 siSwati (Swati)</option> |
|
|
<option value="ve">🇿🇦 Tshivenḓa (Venda)</option> |
|
|
<option value="ts">🇿🇦 Xitsonga (Tsonga)</option> |
|
|
<option value="nr">🇿🇦 isiNdebele (Southern Ndebele)</option> |
|
|
<option value="am">🇪🇹 አማርኛ (Amharic)</option> |
|
|
<option value="ti">🇪🇷 ትግርኛ (Tigrinya)</option> |
|
|
<option value="om">🇪🇹 Afaan Oromoo (Oromo)</option> |
|
|
<option value="so">🇸🇴 Soomaali (Somali)</option> |
|
|
<option value="ha">🇳🇬 Hausa</option> |
|
|
<option value="yo">🇳🇬 Yorùbá (Yoruba)</option> |
|
|
<option value="ig">🇳🇬 Igbo</option> |
|
|
<option value="ff">🇸🇳 Fulfulde (Fulani)</option> |
|
|
<option value="wo">🇸🇳 Wolof</option> |
|
|
<option value="bm">🇲🇱 Bamanankan (Bambara)</option> |
|
|
<option value="rn">🇧🇮 Kirundi (Rundi)</option> |
|
|
<option value="rw">🇷🇼 Kinyarwanda (Rwanda)</option> |
|
|
<option value="lg">🇺🇬 Luganda</option> |
|
|
<option value="ny">🇲🇼 Chichewa (Nyanja)</option> |
|
|
<option value="sn">🇿🇼 chiShona (Shona)</option> |
|
|
<option value="nd">🇿🇼 isiNdebele (Northern Ndebele)</option> |
|
|
</select> |
|
|
</div> |
|
|
|
|
|
<div class="api-key-landing"> |
|
|
<label for="apiKeyLanding" data-translate="api_key_label">🔑 OpenAI API Key</label> |
|
|
<input type="password" id="apiKeyLanding" placeholder="Enter your OpenAI API key" data-translate-placeholder="api_key_placeholder"> |
|
|
</div> |
|
|
|
|
|
<button class="start-btn" id="startBtn" data-translate="start_button">🚀 Start Process Improvement</button> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="main-app" id="mainApp"> |
|
|
<div class="container"> |
|
|
|
|
|
<div class="language-switcher" id="languageSwitcher"> |
|
|
<div class="language-switch-btn" onclick="showLanguageLanding()"> |
|
|
<span data-translate="change_language">🌐 Change Language</span> |
|
|
</div> |
|
|
<div class="mini-clear-cache" onclick="clearAllTranslationCache()" title="Clear translation cache"> |
|
|
<span data-translate="clear_cache_mini">🗑️ Clear Cache</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="api-key-section"> |
|
|
<label for="apiKey" data-translate="api_key_short">🔑 API Key</label> |
|
|
<input type="password" id="apiKey" data-translate-placeholder="api_key_placeholder" autocomplete="off"> |
|
|
</div> |
|
|
|
|
|
<div class="main-content"> |
|
|
|
|
|
<div class="header"> |
|
|
<h1 data-translate="app_title">ContinuousImprovement Pro</h1> |
|
|
<p class="subtitle" data-translate="app_subtitle">Advanced PDCA Methodology & Process Optimization</p> |
|
|
<p class="description" data-translate="app_description">Generate comprehensive PDCA cycle explanations tailored to your specific processes and continuous improvement initiatives</p> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="pdca-steps"> |
|
|
<div class="step-card plan"> |
|
|
<h4 data-translate="step_plan">📋 Plan</h4> |
|
|
<p data-translate="step_plan_desc">Identify & Strategize</p> |
|
|
</div> |
|
|
<div class="step-card do"> |
|
|
<h4 data-translate="step_do">⚡ Do</h4> |
|
|
<p data-translate="step_do_desc">Execute & Implement</p> |
|
|
</div> |
|
|
<div class="step-card check"> |
|
|
<h4 data-translate="step_check">📊 Check</h4> |
|
|
<p data-translate="step_check_desc">Monitor & Evaluate</p> |
|
|
</div> |
|
|
<div class="step-card act"> |
|
|
<h4 data-translate="step_act">🔄 Act</h4> |
|
|
<p data-translate="step_act_desc">Standardize & Improve</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="input-section"> |
|
|
<h3 data-translate="input_title">🔧 Process & Context Input</h3> |
|
|
<p class="description" data-translate="input_description">Describe your process, improvement initiative, or any context where you need to apply PDCA methodology for continuous improvement</p> |
|
|
<textarea id="textInput" data-translate-placeholder="input_placeholder" required></textarea> |
|
|
<div class="char-counter" id="charCounter">0 <span data-translate="characters">characters</span></div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="error-message" id="errorMessage"></div> |
|
|
|
|
|
|
|
|
<button class="generate-btn" id="generatePDCABtn"> |
|
|
<span class="spinner" id="spinner"></span> |
|
|
<span id="buttonText" data-translate="generate_button">🔄 Generate PDCA Guide</span> |
|
|
</button> |
|
|
|
|
|
|
|
|
<div class="output-section"> |
|
|
<h2 data-translate="output_title">📈 Your PDCA Cycle Guide</h2> |
|
|
<div class="output-area" id="apiOutput"></div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="footer"> |
|
|
Created by Shift Mind AI Labs |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
const rtlLanguages = ['ar', 'he', 'fa', 'ur', 'ps', 'ku']; |
|
|
|
|
|
|
|
|
let currentLanguage = 'en'; |
|
|
let currentApiKey = ''; |
|
|
|
|
|
|
|
|
const languageNames = { |
|
|
en: 'English', es: 'Spanish', fr: 'French', de: 'German', zh: 'Chinese', |
|
|
ja: 'Japanese', ko: 'Korean', pt: 'Portuguese', it: 'Italian', ar: 'Arabic', |
|
|
ru: 'Russian', hi: 'Hindi', bn: 'Bengali', ur: 'Urdu', tr: 'Turkish', |
|
|
pl: 'Polish', nl: 'Dutch', sv: 'Swedish', da: 'Danish', no: 'Norwegian', |
|
|
fi: 'Finnish', is: 'Icelandic', cs: 'Czech', sk: 'Slovak', hu: 'Hungarian', |
|
|
ro: 'Romanian', bg: 'Bulgarian', hr: 'Croatian', sr: 'Serbian', sl: 'Slovenian', |
|
|
mk: 'Macedonian', sq: 'Albanian', lv: 'Latvian', lt: 'Lithuanian', et: 'Estonian', |
|
|
mt: 'Maltese', ga: 'Irish', cy: 'Welsh', eu: 'Basque', ca: 'Catalan', |
|
|
gl: 'Galician', el: 'Greek', he: 'Hebrew', fa: 'Persian', ps: 'Pashto', |
|
|
ku: 'Kurdish', az: 'Azerbaijani', kk: 'Kazakh', ky: 'Kyrgyz', uz: 'Uzbek', |
|
|
tk: 'Turkmen', tg: 'Tajik', mn: 'Mongolian', ka: 'Georgian', hy: 'Armenian', |
|
|
th: 'Thai', vi: 'Vietnamese', lo: 'Lao', km: 'Khmer', my: 'Myanmar', |
|
|
si: 'Sinhala', ta: 'Tamil', te: 'Telugu', kn: 'Kannada', ml: 'Malayalam', |
|
|
gu: 'Gujarati', pa: 'Punjabi', or: 'Odia', as: 'Assamese', ne: 'Nepali', |
|
|
dz: 'Dzongkha', bo: 'Tibetan', id: 'Indonesian', ms: 'Malay', tl: 'Filipino', |
|
|
ceb: 'Cebuano', haw: 'Hawaiian', mi: 'Maori', sm: 'Samoan', to: 'Tongan', |
|
|
fj: 'Fijian', mg: 'Malagasy', sw: 'Swahili', zu: 'Zulu', xh: 'Xhosa', |
|
|
af: 'Afrikaans', st: 'Southern Sotho', tn: 'Tswana', ss: 'Swati', ve: 'Venda', |
|
|
ts: 'Tsonga', nr: 'Southern Ndebele', am: 'Amharic', ti: 'Tigrinya', om: 'Oromo', |
|
|
so: 'Somali', ha: 'Hausa', yo: 'Yoruba', ig: 'Igbo', ff: 'Fulani', |
|
|
wo: 'Wolof', bm: 'Bambara', rn: 'Rundi', rw: 'Rwanda', lg: 'Luganda', |
|
|
ny: 'Chichewa', sn: 'Shona', nd: 'Northern Ndebele' |
|
|
}; |
|
|
|
|
|
|
|
|
const CACHE_PREFIX = 'continuousimprovement_translations_'; |
|
|
const CACHE_VERSION = '1.0'; |
|
|
|
|
|
|
|
|
function isLanguageCached(language) { |
|
|
const cacheKey = CACHE_PREFIX + language; |
|
|
const cached = localStorage.getItem(cacheKey); |
|
|
return cached !== null; |
|
|
} |
|
|
|
|
|
|
|
|
function saveTranslationsToCache(language, translations) { |
|
|
const cacheKey = CACHE_PREFIX + language; |
|
|
const cacheData = { |
|
|
version: CACHE_VERSION, |
|
|
timestamp: Date.now(), |
|
|
translations: translations |
|
|
}; |
|
|
localStorage.setItem(cacheKey, JSON.stringify(cacheData)); |
|
|
console.log(`Translations cached for ${language}`); |
|
|
} |
|
|
|
|
|
|
|
|
function loadTranslationsFromCache(language) { |
|
|
const cacheKey = CACHE_PREFIX + language; |
|
|
const cached = localStorage.getItem(cacheKey); |
|
|
|
|
|
if (cached) { |
|
|
try { |
|
|
const cacheData = JSON.parse(cached); |
|
|
if (cacheData.version === CACHE_VERSION) { |
|
|
console.log(`Translations loaded from cache for ${language}`); |
|
|
return cacheData.translations; |
|
|
} |
|
|
} catch (error) { |
|
|
console.error('Error parsing cached translations:', error); |
|
|
} |
|
|
} |
|
|
return null; |
|
|
} |
|
|
|
|
|
|
|
|
function getCachedLanguages() { |
|
|
const cachedLanguages = []; |
|
|
for (let i = 0; i < localStorage.length; i++) { |
|
|
const key = localStorage.key(i); |
|
|
if (key && key.startsWith(CACHE_PREFIX)) { |
|
|
const language = key.replace(CACHE_PREFIX, ''); |
|
|
cachedLanguages.push(language); |
|
|
} |
|
|
} |
|
|
return cachedLanguages; |
|
|
} |
|
|
|
|
|
|
|
|
function clearAllTranslationCache() { |
|
|
const cachedLanguages = getCachedLanguages(); |
|
|
|
|
|
if (cachedLanguages.length === 0) { |
|
|
alert('No cached translations to clear.'); |
|
|
return; |
|
|
} |
|
|
|
|
|
const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', '); |
|
|
const confirmMessage = `Are you sure you want to clear all cached translations?\n\nCached languages: ${languageList}\n\nThis will require re-downloading translations when switching languages.`; |
|
|
|
|
|
if (confirm(confirmMessage)) { |
|
|
|
|
|
cachedLanguages.forEach(language => { |
|
|
const cacheKey = CACHE_PREFIX + language; |
|
|
localStorage.removeItem(cacheKey); |
|
|
}); |
|
|
|
|
|
|
|
|
updateCacheStatus(currentLanguage); |
|
|
updateCacheStatusDisplay(); |
|
|
|
|
|
alert(`Cache cleared successfully!\n\n${cachedLanguages.length} language(s) removed from cache.`); |
|
|
|
|
|
|
|
|
if (currentLanguage !== 'en' && cachedLanguages.includes(currentLanguage)) { |
|
|
if (confirm('Would you like to reload the current language translations?')) { |
|
|
applyLanguage(currentLanguage); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function updateCacheStatus(language) { |
|
|
const cacheStatus = document.getElementById('cacheStatus'); |
|
|
const isCached = isLanguageCached(language); |
|
|
|
|
|
if (language === 'en') { |
|
|
cacheStatus.classList.remove('cached', 'translating'); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (isCached) { |
|
|
cacheStatus.textContent = '💾 Translations cached - instant loading!'; |
|
|
cacheStatus.classList.add('cached'); |
|
|
cacheStatus.classList.remove('translating'); |
|
|
} else { |
|
|
cacheStatus.textContent = '🔄 First time translation - will be cached for future use'; |
|
|
cacheStatus.classList.add('translating'); |
|
|
cacheStatus.classList.remove('cached'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function updateCacheStatusDisplay() { |
|
|
const cacheStatusDisplay = document.getElementById('cacheStatusDisplay'); |
|
|
const clearCacheBtn = document.getElementById('clearCacheBtn'); |
|
|
const cachedLanguages = getCachedLanguages(); |
|
|
|
|
|
if (cachedLanguages.length === 0) { |
|
|
cacheStatusDisplay.textContent = '📭 No cached translations'; |
|
|
cacheStatusDisplay.className = 'cache-status-display no-cache'; |
|
|
clearCacheBtn.disabled = true; |
|
|
} else { |
|
|
const languageList = cachedLanguages.map(lang => languageNames[lang] || lang).join(', '); |
|
|
cacheStatusDisplay.textContent = `💾 ${cachedLanguages.length} language(s) cached: ${languageList}`; |
|
|
cacheStatusDisplay.className = 'cache-status-display'; |
|
|
clearCacheBtn.disabled = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function initializeApp() { |
|
|
|
|
|
const savedLanguage = localStorage.getItem('continuousimprovement_language') || 'en'; |
|
|
const savedApiKey = localStorage.getItem('continuous_improvement_api_key') || ''; |
|
|
|
|
|
currentLanguage = savedLanguage; |
|
|
currentApiKey = savedApiKey; |
|
|
|
|
|
|
|
|
document.getElementById('languageSelect').value = currentLanguage; |
|
|
document.getElementById('apiKeyLanding').value = currentApiKey; |
|
|
|
|
|
|
|
|
applyDirection(currentLanguage); |
|
|
|
|
|
|
|
|
updateCacheStatus(currentLanguage); |
|
|
updateCacheStatusDisplay(); |
|
|
|
|
|
|
|
|
if (currentApiKey && currentLanguage) { |
|
|
showMainApp(); |
|
|
} else { |
|
|
showLanguageLanding(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function applyDirection(language) { |
|
|
currentLanguage = language; |
|
|
|
|
|
|
|
|
document.documentElement.lang = language; |
|
|
document.documentElement.dir = rtlLanguages.includes(language) ? 'rtl' : 'ltr'; |
|
|
|
|
|
|
|
|
localStorage.setItem('continuousimprovement_language', language); |
|
|
|
|
|
|
|
|
updateCacheStatus(language); |
|
|
} |
|
|
|
|
|
|
|
|
async function translateText(text, targetLanguage) { |
|
|
if (!currentApiKey) { |
|
|
throw new Error('API key is required for translation'); |
|
|
} |
|
|
|
|
|
const languageName = languageNames[targetLanguage] || 'English'; |
|
|
|
|
|
const prompt = `Translate the following text to ${languageName}. Provide ONLY the exact translation without any explanations, additional information, or formatting: |
|
|
|
|
|
"${text}"`; |
|
|
|
|
|
const payload = { |
|
|
model: "gpt-4o-mini", |
|
|
messages: [{ role: "user", content: prompt }], |
|
|
max_tokens: 500, |
|
|
temperature: 0.1 |
|
|
}; |
|
|
|
|
|
const response = await fetch("https://api.openai.com/v1/chat/completions", { |
|
|
method: "POST", |
|
|
headers: { |
|
|
"Content-Type": "application/json", |
|
|
"Authorization": `Bearer ${currentApiKey}` |
|
|
}, |
|
|
body: JSON.stringify(payload) |
|
|
}); |
|
|
|
|
|
if (!response.ok) { |
|
|
const errorData = await response.json(); |
|
|
throw new Error(errorData.error?.message || "Translation API request failed"); |
|
|
} |
|
|
|
|
|
const data = await response.json(); |
|
|
return data.choices[0].message.content.trim(); |
|
|
} |
|
|
|
|
|
|
|
|
function applyCachedTranslations(translations) { |
|
|
|
|
|
Object.keys(translations.texts).forEach(originalText => { |
|
|
const translation = translations.texts[originalText]; |
|
|
const elements = document.querySelectorAll(`[data-translate]`); |
|
|
|
|
|
elements.forEach(element => { |
|
|
const originalElementText = element.getAttribute('data-original-text') || element.textContent; |
|
|
if (originalElementText === originalText) { |
|
|
element.textContent = translation; |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
Object.keys(translations.placeholders).forEach(originalPlaceholder => { |
|
|
const translation = translations.placeholders[originalPlaceholder]; |
|
|
const elements = document.querySelectorAll(`[data-translate-placeholder]`); |
|
|
|
|
|
elements.forEach(element => { |
|
|
const originalElementPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder; |
|
|
if (originalElementPlaceholder === originalPlaceholder) { |
|
|
element.placeholder = translation; |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
async function translateInterface(targetLanguage) { |
|
|
if (targetLanguage === 'en') { |
|
|
|
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
const cachedTranslations = loadTranslationsFromCache(targetLanguage); |
|
|
if (cachedTranslations) { |
|
|
|
|
|
console.log('Using cached translations for', targetLanguage); |
|
|
applyCachedTranslations(cachedTranslations); |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
showTranslationOverlay(); |
|
|
|
|
|
try { |
|
|
|
|
|
const elements = document.querySelectorAll('[data-translate]'); |
|
|
const placeholderElements = document.querySelectorAll('[data-translate-placeholder]'); |
|
|
|
|
|
|
|
|
const textsToTranslate = []; |
|
|
const placeholdersToTranslate = []; |
|
|
const elementMap = new Map(); |
|
|
|
|
|
elements.forEach(element => { |
|
|
const originalText = element.getAttribute('data-original-text') || element.textContent; |
|
|
if (!element.getAttribute('data-original-text')) { |
|
|
element.setAttribute('data-original-text', originalText); |
|
|
} |
|
|
textsToTranslate.push(originalText); |
|
|
elementMap.set(originalText, element); |
|
|
}); |
|
|
|
|
|
placeholderElements.forEach(element => { |
|
|
const originalPlaceholder = element.getAttribute('data-original-placeholder') || element.placeholder; |
|
|
if (!element.getAttribute('data-original-placeholder')) { |
|
|
element.setAttribute('data-original-placeholder', originalPlaceholder); |
|
|
} |
|
|
placeholdersToTranslate.push(originalPlaceholder); |
|
|
elementMap.set(originalPlaceholder, element); |
|
|
}); |
|
|
|
|
|
|
|
|
const translationsCache = { |
|
|
texts: {}, |
|
|
placeholders: {} |
|
|
}; |
|
|
|
|
|
|
|
|
const batchSize = 10; |
|
|
const allTexts = [...textsToTranslate, ...placeholdersToTranslate]; |
|
|
|
|
|
for (let i = 0; i < allTexts.length; i += batchSize) { |
|
|
const batch = allTexts.slice(i, i + batchSize); |
|
|
|
|
|
|
|
|
updateTranslationProgress(i, allTexts.length); |
|
|
|
|
|
|
|
|
const translations = await Promise.all( |
|
|
batch.map(text => translateText(text, targetLanguage)) |
|
|
); |
|
|
|
|
|
|
|
|
batch.forEach((originalText, index) => { |
|
|
const element = elementMap.get(originalText); |
|
|
const translation = translations[index]; |
|
|
|
|
|
if (element.hasAttribute('data-translate')) { |
|
|
element.textContent = translation; |
|
|
translationsCache.texts[originalText] = translation; |
|
|
} else if (element.hasAttribute('data-translate-placeholder')) { |
|
|
element.placeholder = translation; |
|
|
translationsCache.placeholders[originalText] = translation; |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
saveTranslationsToCache(targetLanguage, translationsCache); |
|
|
|
|
|
|
|
|
updateCacheStatus(targetLanguage); |
|
|
updateCacheStatusDisplay(); |
|
|
|
|
|
} catch (error) { |
|
|
console.error('Translation error:', error); |
|
|
showError('Translation failed: ' + error.message); |
|
|
} finally { |
|
|
hideTranslationOverlay(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function showTranslationOverlay() { |
|
|
document.getElementById('translationOverlay').style.display = 'flex'; |
|
|
} |
|
|
|
|
|
|
|
|
function hideTranslationOverlay() { |
|
|
document.getElementById('translationOverlay').style.display = 'none'; |
|
|
} |
|
|
|
|
|
|
|
|
function updateTranslationProgress(current, total) { |
|
|
const percentage = Math.round((current / total) * 100); |
|
|
document.getElementById('translationMessage').textContent = |
|
|
`Translating interface... ${percentage}% complete (will be cached for future use)`; |
|
|
} |
|
|
|
|
|
|
|
|
async function applyLanguage(language) { |
|
|
applyDirection(language); |
|
|
|
|
|
if (language !== 'en') { |
|
|
await translateInterface(language); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function showLanguageLanding() { |
|
|
document.getElementById('languageLanding').style.display = 'block'; |
|
|
document.getElementById('mainApp').style.display = 'none'; |
|
|
} |
|
|
|
|
|
|
|
|
function showMainApp() { |
|
|
document.getElementById('languageLanding').style.display = 'none'; |
|
|
document.getElementById('mainApp').style.display = 'block'; |
|
|
|
|
|
|
|
|
document.getElementById('apiKey').value = currentApiKey; |
|
|
} |
|
|
|
|
|
|
|
|
document.getElementById('startBtn').addEventListener('click', async function() { |
|
|
const selectedLanguage = document.getElementById('languageSelect').value; |
|
|
const apiKey = document.getElementById('apiKeyLanding').value.trim(); |
|
|
|
|
|
if (!apiKey) { |
|
|
alert('Please enter your OpenAI API key'); |
|
|
return; |
|
|
} |
|
|
|
|
|
currentLanguage = selectedLanguage; |
|
|
currentApiKey = apiKey; |
|
|
|
|
|
|
|
|
localStorage.setItem('continuous_improvement_api_key', apiKey); |
|
|
|
|
|
|
|
|
await applyLanguage(selectedLanguage); |
|
|
|
|
|
|
|
|
showMainApp(); |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('languageSelect').addEventListener('change', async function() { |
|
|
const selectedLanguage = this.value; |
|
|
updateCacheStatus(selectedLanguage); |
|
|
|
|
|
if (currentApiKey) { |
|
|
await applyLanguage(selectedLanguage); |
|
|
} else { |
|
|
applyDirection(selectedLanguage); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('clearCacheBtn').addEventListener('click', clearAllTranslationCache); |
|
|
|
|
|
|
|
|
const textInput = document.getElementById('textInput'); |
|
|
const charCounter = document.getElementById('charCounter'); |
|
|
|
|
|
textInput.addEventListener('input', function() { |
|
|
const count = this.value.length; |
|
|
const charactersText = charCounter.querySelector('[data-translate="characters"]')?.textContent || 'characters'; |
|
|
charCounter.innerHTML = `${count} <span data-translate="characters">${charactersText}</span>`; |
|
|
|
|
|
if (count > 5000) { |
|
|
charCounter.style.color = 'var(--warning)'; |
|
|
} else { |
|
|
charCounter.style.color = 'var(--text-secondary)'; |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
function showError(message) { |
|
|
const errorDiv = document.getElementById('errorMessage'); |
|
|
errorDiv.textContent = message; |
|
|
errorDiv.style.display = 'block'; |
|
|
setTimeout(() => { |
|
|
errorDiv.style.display = 'none'; |
|
|
}, 5000); |
|
|
} |
|
|
|
|
|
|
|
|
async function callAPI(prompt) { |
|
|
const apiKey = currentApiKey; |
|
|
|
|
|
if (!apiKey) { |
|
|
throw new Error('Please enter your OpenAI API key'); |
|
|
} |
|
|
|
|
|
const payload = { |
|
|
model: "gpt-4o-mini", |
|
|
messages: [{ role: "user", content: prompt }], |
|
|
max_tokens: 3500, |
|
|
temperature: 0.3 |
|
|
}; |
|
|
|
|
|
const response = await fetch("https://api.openai.com/v1/chat/completions", { |
|
|
method: "POST", |
|
|
headers: { |
|
|
"Content-Type": "application/json", |
|
|
"Authorization": `Bearer ${apiKey}` |
|
|
}, |
|
|
body: JSON.stringify(payload) |
|
|
}); |
|
|
|
|
|
if (!response.ok) { |
|
|
const errorData = await response.json(); |
|
|
throw new Error(errorData.error?.message || "API request failed"); |
|
|
} |
|
|
|
|
|
const data = await response.json(); |
|
|
return data.choices[0].message.content; |
|
|
} |
|
|
|
|
|
|
|
|
function buildPDCAPrompt() { |
|
|
const inputText = document.getElementById('textInput').value.trim(); |
|
|
const languageName = languageNames[currentLanguage] || 'English'; |
|
|
|
|
|
return `Based on the following process context and improvement scenario: |
|
|
|
|
|
--------------------- |
|
|
${inputText} |
|
|
--------------------- |
|
|
|
|
|
Please generate a comprehensive, structured, and professionally formatted explanation of the PDCA Cycle (Plan-Do-Check-Act) that directly reflects and addresses the specific context provided above. The output should be tailored to the user's process scenario and formatted as clean HTML with inline CSS for professional presentation. Write ENTIRELY in ${languageName} language. |
|
|
|
|
|
**Required Structure:** |
|
|
|
|
|
1. **Concept & Overview** |
|
|
- Provide a thorough description of the PDCA Cycle as an iterative management method |
|
|
- Explain its role in controlling and continuously improving processes and products |
|
|
- Include historical background (Deming Cycle, Shewhart Cycle) and core principles |
|
|
- Connect the explanation to the specific context provided in the input |
|
|
- Discuss how the cycle promotes systematic continuous improvement |
|
|
|
|
|
2. **Contextual Application** |
|
|
- Explain how the PDCA cycle applies to the specific process described in the input |
|
|
- Reference relevant aspects of the process context and improvement challenges |
|
|
- Provide personalized insights based on the industry or domain mentioned |
|
|
- Discuss the potential impact and benefits for the specific scenario |
|
|
|
|
|
3. **The Four PDCA Steps (Detailed Analysis)** |
|
|
Based on the process context, provide comprehensive coverage of each step: |
|
|
|
|
|
**📋 Plan (Identify & Strategize)** |
|
|
- Problem identification and root cause analysis techniques |
|
|
- Objective setting using SMART criteria |
|
|
- Data collection and baseline establishment |
|
|
- Solution development and planning methodologies |
|
|
- Risk assessment and mitigation planning |
|
|
- Resource allocation and timeline development |
|
|
- Specific examples relevant to the user's context |
|
|
|
|
|
**⚡ Do (Execute & Implement)** |
|
|
- Implementation strategies and change management |
|
|
- Pilot testing and small-scale implementation |
|
|
- Training and communication requirements |
|
|
- Documentation and process standardization |
|
|
- Monitoring during implementation |
|
|
- Specific execution steps for the user's scenario |
|
|
|
|
|
**📊 Check (Monitor & Evaluate)** |
|
|
- Data collection and measurement techniques |
|
|
- Performance indicators and metrics selection |
|
|
- Comparison against objectives and baselines |
|
|
- Statistical analysis and trend identification |
|
|
- Gap analysis and variance investigation |
|
|
- Specific monitoring approaches for the user's context |
|
|
|
|
|
**🔄 Act (Standardize & Improve)** |
|
|
- Standardization of successful improvements |
|
|
- Process documentation and knowledge transfer |
|
|
- Corrective action for unsuccessful attempts |
|
|
- Scaling successful changes across the organization |
|
|
- Preparation for the next PDCA cycle |
|
|
- Specific standardization steps for the user's scenario |
|
|
|
|
|
4. **Implementation Strategy** |
|
|
- Step-by-step process for applying PDCA to the user's specific context |
|
|
- Team formation and stakeholder engagement |
|
|
- Tools and techniques for each PDCA phase |
|
|
- Timeline and milestone planning |
|
|
- Communication and change management strategies |
|
|
|
|
|
5. **Benefits & Value Proposition** |
|
|
- Advantages of using the PDCA Cycle for continuous improvement |
|
|
- Cultural transformation and organizational learning benefits |
|
|
- Risk reduction and quality improvement outcomes |
|
|
- Cost savings and efficiency gains |
|
|
- Specific benefits for the user's context and industry |
|
|
|
|
|
6. **Challenges & Best Practices** |
|
|
- Common implementation challenges and obstacles |
|
|
- Strategies to overcome resistance to change |
|
|
- Best practices for successful PDCA implementation |
|
|
- Tips for maintaining momentum and engagement |
|
|
- Lessons learned from successful implementations |
|
|
|
|
|
7. **Advanced Considerations** |
|
|
- Integration with other improvement methodologies (Lean, Six Sigma, Kaizen) |
|
|
- Digital tools and technology enablers |
|
|
- Scaling PDCA across multiple processes or departments |
|
|
- Long-term sustainability and continuous improvement culture |
|
|
- Performance measurement and ROI tracking |
|
|
|
|
|
8. **Complementary Tools & Techniques** |
|
|
- Quality tools that enhance PDCA effectiveness |
|
|
- Data analysis and statistical methods |
|
|
- Project management and change management frameworks |
|
|
- Technology solutions and automation opportunities |
|
|
- Training and capability development programs |
|
|
|
|
|
**Formatting Requirements:** |
|
|
- Use clean HTML with inline CSS for professional presentation |
|
|
- Include proper headings (h3, h4) with attractive styling |
|
|
- Use bullet points and numbered lists for clarity |
|
|
- Apply consistent color scheme (blues for process improvement themes) |
|
|
- Ensure responsive design and readability |
|
|
- Make the content scannable with clear visual hierarchy |
|
|
- Include specific examples relevant to the user's process context |
|
|
|
|
|
**Tone:** Professional, educational, and directly relevant to the user's specific process context. Focus on practical, actionable guidance that can be immediately applied to their continuous improvement needs. |
|
|
|
|
|
Return only the complete HTML content with inline CSS - no additional text or explanations outside the HTML.`; |
|
|
} |
|
|
|
|
|
|
|
|
function validateInputs() { |
|
|
const inputText = document.getElementById('textInput').value.trim(); |
|
|
|
|
|
if (!inputText) { |
|
|
document.getElementById('textInput').focus(); |
|
|
throw new Error('Please enter your process context or improvement scenario'); |
|
|
} |
|
|
|
|
|
if (inputText.length < 50) { |
|
|
document.getElementById('textInput').focus(); |
|
|
throw new Error('Please provide at least 50 characters for meaningful PDCA analysis'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
document.getElementById('generatePDCABtn').addEventListener('click', async function() { |
|
|
const button = this; |
|
|
const buttonText = document.getElementById('buttonText'); |
|
|
const spinner = document.getElementById('spinner'); |
|
|
const outputArea = document.getElementById('apiOutput'); |
|
|
|
|
|
try { |
|
|
|
|
|
validateInputs(); |
|
|
|
|
|
|
|
|
button.disabled = true; |
|
|
spinner.style.display = 'inline-block'; |
|
|
buttonText.textContent = 'Generating Guide...'; |
|
|
|
|
|
|
|
|
outputArea.innerHTML = ''; |
|
|
|
|
|
|
|
|
const prompt = buildPDCAPrompt(); |
|
|
const result = await callAPI(prompt); |
|
|
|
|
|
|
|
|
outputArea.innerHTML = result; |
|
|
|
|
|
} catch (error) { |
|
|
showError(error.message); |
|
|
outputArea.innerHTML = ''; |
|
|
} finally { |
|
|
|
|
|
button.disabled = false; |
|
|
spinner.style.display = 'none'; |
|
|
buttonText.textContent = '🔄 Generate PDCA Guide'; |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.addEventListener('keydown', function(e) { |
|
|
if (e.ctrlKey && e.key === 'Enter') { |
|
|
e.preventDefault(); |
|
|
document.getElementById('generatePDCABtn').click(); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('apiKeyLanding').addEventListener('input', function() { |
|
|
currentApiKey = this.value; |
|
|
localStorage.setItem('continuous_improvement_api_key', this.value); |
|
|
document.getElementById('apiKey').value = this.value; |
|
|
}); |
|
|
|
|
|
document.getElementById('apiKey').addEventListener('input', function() { |
|
|
currentApiKey = this.value; |
|
|
localStorage.setItem('continuous_improvement_api_key', this.value); |
|
|
document.getElementById('apiKeyLanding').value = this.value; |
|
|
}); |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', initializeApp); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|
|
|
|