- Fix Invalid fitness_goal error: frontend values (general, hypertrophy) did not match backend enum (general_fitness, muscle_gain) - Fix Invalid cardio_preference error: frontend values (running, cycling) did not match backend enum (low, moderate, high) - Convert both fields to multi-select checkboxes - Update backend validation to accept all frontend values with multi-enum Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2922 lines
106 KiB
HTML
2922 lines
106 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="tr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>FitLife - Saglik & Fitness</title>
|
|
<style>
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
:root {
|
|
--green: #2ecc71;
|
|
--green-dark: #27ae60;
|
|
--dark: #2c3e50;
|
|
--dark-light: #34495e;
|
|
--light: #ecf0f1;
|
|
--white: #ffffff;
|
|
--gray: #95a5a6;
|
|
--gray-light: #bdc3c7;
|
|
--red: #e74c3c;
|
|
--orange: #f39c12;
|
|
--blue: #3498db;
|
|
--yellow: #f1c40f;
|
|
--purple: #9b59b6;
|
|
--shadow: 0 2px 12px rgba(0,0,0,0.1);
|
|
--shadow-lg: 0 8px 30px rgba(0,0,0,0.12);
|
|
--radius: 12px;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, sans-serif;
|
|
background: var(--light);
|
|
color: var(--dark);
|
|
line-height: 1.6;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
/* Navbar */
|
|
.navbar {
|
|
background: var(--dark);
|
|
color: var(--white);
|
|
padding: 0 20px;
|
|
height: 60px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 100;
|
|
box-shadow: var(--shadow);
|
|
}
|
|
.navbar .brand {
|
|
font-size: 1.4rem;
|
|
font-weight: 700;
|
|
color: var(--green);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.navbar .brand span { color: var(--white); }
|
|
.navbar .user-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
.navbar .user-name {
|
|
font-size: 0.9rem;
|
|
color: var(--gray-light);
|
|
}
|
|
|
|
/* Buttons */
|
|
.btn {
|
|
padding: 8px 20px;
|
|
border: none;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
transition: all 0.2s;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.btn-primary { background: var(--green); color: var(--white); }
|
|
.btn-primary:hover { background: var(--green-dark); }
|
|
.btn-secondary { background: var(--dark-light); color: var(--white); }
|
|
.btn-secondary:hover { background: var(--dark); }
|
|
.btn-danger { background: var(--red); color: var(--white); }
|
|
.btn-danger:hover { opacity: 0.9; }
|
|
.btn-outline { background: transparent; color: var(--green); border: 2px solid var(--green); }
|
|
.btn-outline:hover { background: var(--green); color: var(--white); }
|
|
.btn-sm { padding: 6px 14px; font-size: 0.8rem; }
|
|
.btn-lg { padding: 12px 32px; font-size: 1.05rem; }
|
|
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
|
|
|
|
/* Container */
|
|
.container {
|
|
max-width: 1100px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
|
|
/* Auth pages */
|
|
.auth-page {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
min-height: calc(100vh - 60px);
|
|
padding: 20px;
|
|
}
|
|
.auth-card {
|
|
background: var(--white);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow-lg);
|
|
padding: 40px;
|
|
width: 100%;
|
|
max-width: 420px;
|
|
}
|
|
.auth-card h2 {
|
|
text-align: center;
|
|
margin-bottom: 8px;
|
|
color: var(--dark);
|
|
}
|
|
.auth-card .subtitle {
|
|
text-align: center;
|
|
color: var(--gray);
|
|
margin-bottom: 28px;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
/* Forms */
|
|
.form-group {
|
|
margin-bottom: 18px;
|
|
}
|
|
.form-group label {
|
|
display: block;
|
|
font-weight: 600;
|
|
font-size: 0.85rem;
|
|
margin-bottom: 6px;
|
|
color: var(--dark-light);
|
|
}
|
|
.form-group input,
|
|
.form-group select,
|
|
.form-group textarea {
|
|
width: 100%;
|
|
padding: 10px 14px;
|
|
border: 2px solid var(--gray-light);
|
|
border-radius: 8px;
|
|
font-size: 0.95rem;
|
|
transition: border-color 0.2s;
|
|
background: var(--white);
|
|
}
|
|
.form-group input:focus,
|
|
.form-group select:focus,
|
|
.form-group textarea:focus {
|
|
outline: none;
|
|
border-color: var(--green);
|
|
}
|
|
.form-group textarea {
|
|
resize: vertical;
|
|
min-height: 60px;
|
|
}
|
|
.form-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 12px;
|
|
}
|
|
.form-row-3 {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1fr;
|
|
gap: 12px;
|
|
}
|
|
.error-msg {
|
|
color: var(--red);
|
|
font-size: 0.85rem;
|
|
margin-top: 6px;
|
|
}
|
|
.success-msg {
|
|
color: var(--green-dark);
|
|
font-size: 0.85rem;
|
|
margin-top: 6px;
|
|
}
|
|
.link-text {
|
|
text-align: center;
|
|
margin-top: 20px;
|
|
font-size: 0.9rem;
|
|
color: var(--gray);
|
|
}
|
|
.link-text a {
|
|
color: var(--green);
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
font-weight: 600;
|
|
}
|
|
.link-text a:hover { text-decoration: underline; }
|
|
|
|
/* Radio group */
|
|
.radio-group {
|
|
display: flex;
|
|
gap: 12px;
|
|
flex-wrap: wrap;
|
|
margin-top: 4px;
|
|
}
|
|
.radio-group label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
cursor: pointer;
|
|
padding: 8px 14px;
|
|
border: 2px solid var(--gray-light);
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
font-size: 0.9rem;
|
|
transition: all 0.2s;
|
|
}
|
|
.radio-group label:hover {
|
|
border-color: var(--green);
|
|
}
|
|
.radio-group input[type="radio"] {
|
|
width: auto;
|
|
margin: 0;
|
|
}
|
|
.radio-group input[type="radio"]:checked + span {
|
|
color: var(--green-dark);
|
|
font-weight: 600;
|
|
}
|
|
.radio-group label:has(input:checked) {
|
|
border-color: var(--green);
|
|
background: rgba(46, 204, 113, 0.05);
|
|
}
|
|
.radio-desc {
|
|
font-size: 0.75rem;
|
|
color: var(--gray);
|
|
display: block;
|
|
}
|
|
.hint {
|
|
font-size: 0.8rem;
|
|
color: var(--gray);
|
|
font-weight: 400;
|
|
}
|
|
|
|
/* Checkbox group */
|
|
.checkbox-group {
|
|
display: flex;
|
|
gap: 10px;
|
|
flex-wrap: wrap;
|
|
margin-top: 4px;
|
|
}
|
|
.checkbox-group label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
cursor: pointer;
|
|
padding: 6px 12px;
|
|
border: 2px solid var(--gray-light);
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
font-size: 0.85rem;
|
|
transition: all 0.2s;
|
|
}
|
|
.checkbox-group label:hover {
|
|
border-color: var(--green);
|
|
}
|
|
.checkbox-group input[type="checkbox"] {
|
|
width: auto;
|
|
margin: 0;
|
|
}
|
|
.checkbox-group label:has(input:checked) {
|
|
border-color: var(--green);
|
|
background: rgba(46, 204, 113, 0.05);
|
|
}
|
|
|
|
/* Toggle switch */
|
|
.toggle-switch {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
cursor: pointer;
|
|
margin-top: 4px;
|
|
}
|
|
.toggle-switch input { display: none; }
|
|
.toggle-slider {
|
|
width: 48px;
|
|
height: 26px;
|
|
background: var(--gray-light);
|
|
border-radius: 26px;
|
|
position: relative;
|
|
transition: background 0.2s;
|
|
flex-shrink: 0;
|
|
}
|
|
.toggle-slider::after {
|
|
content: '';
|
|
position: absolute;
|
|
width: 20px;
|
|
height: 20px;
|
|
background: var(--white);
|
|
border-radius: 50%;
|
|
top: 3px;
|
|
left: 3px;
|
|
transition: left 0.2s;
|
|
}
|
|
.toggle-switch input:checked + .toggle-slider {
|
|
background: var(--green);
|
|
}
|
|
.toggle-switch input:checked + .toggle-slider::after {
|
|
left: 25px;
|
|
}
|
|
|
|
/* Location cards */
|
|
.location-cards {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 12px;
|
|
margin-top: 8px;
|
|
}
|
|
.location-card {
|
|
border: 2px solid var(--gray-light);
|
|
border-radius: var(--radius);
|
|
padding: 20px 14px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
.location-card:hover {
|
|
border-color: var(--green);
|
|
}
|
|
.location-card.selected {
|
|
border-color: var(--green);
|
|
background: rgba(46, 204, 113, 0.07);
|
|
}
|
|
.location-card .loc-icon {
|
|
font-size: 2rem;
|
|
margin-bottom: 8px;
|
|
}
|
|
.location-card .loc-title {
|
|
font-weight: 700;
|
|
font-size: 1rem;
|
|
margin-bottom: 4px;
|
|
}
|
|
.location-card .loc-desc {
|
|
font-size: 0.8rem;
|
|
color: var(--gray);
|
|
}
|
|
|
|
/* Medical toggle row */
|
|
.medical-toggle-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12px 0;
|
|
border-bottom: 1px solid var(--light);
|
|
}
|
|
.medical-toggle-row:last-child { border-bottom: none; }
|
|
.medical-toggle-row .med-label {
|
|
font-weight: 600;
|
|
font-size: 0.9rem;
|
|
}
|
|
.medical-detail-fields {
|
|
padding: 12px 16px;
|
|
background: #fef9e7;
|
|
border: 1px solid #f9e79f;
|
|
border-radius: 8px;
|
|
margin-bottom: 12px;
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
/* Profile setup */
|
|
.profile-setup {
|
|
max-width: 700px;
|
|
margin: 30px auto;
|
|
background: var(--white);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow-lg);
|
|
padding: 36px;
|
|
}
|
|
.profile-setup h2 {
|
|
margin-bottom: 6px;
|
|
}
|
|
.profile-setup .subtitle {
|
|
color: var(--gray);
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
/* Progress bar */
|
|
.progress-bar-container {
|
|
width: 100%;
|
|
height: 8px;
|
|
background: var(--gray-light);
|
|
border-radius: 4px;
|
|
margin-bottom: 8px;
|
|
overflow: hidden;
|
|
}
|
|
.progress-bar-fill {
|
|
height: 100%;
|
|
background: var(--green);
|
|
border-radius: 4px;
|
|
transition: width 0.3s ease;
|
|
}
|
|
.step-label {
|
|
text-align: center;
|
|
font-size: 0.85rem;
|
|
color: var(--gray);
|
|
margin-bottom: 24px;
|
|
}
|
|
.step-indicator {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
margin-bottom: 8px;
|
|
}
|
|
.step-dot {
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
background: var(--gray-light);
|
|
transition: background 0.2s;
|
|
}
|
|
.step-dot.active { background: var(--green); }
|
|
.step-dot.done { background: var(--green-dark); }
|
|
.step-buttons {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-top: 24px;
|
|
}
|
|
|
|
/* Conditional fields container */
|
|
.cond-fields {
|
|
background: #fef9e7;
|
|
border: 1px solid #f9e79f;
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
margin-top: 12px;
|
|
transition: all 0.3s;
|
|
}
|
|
.cond-fields-blue {
|
|
background: #eaf2f8;
|
|
border: 1px solid #aed6f1;
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
margin-top: 12px;
|
|
}
|
|
.info-box {
|
|
background: #d5f5e3;
|
|
border-left: 4px solid var(--green);
|
|
border-radius: 8px;
|
|
padding: 14px 18px;
|
|
margin-top: 12px;
|
|
font-size: 0.9rem;
|
|
color: var(--green-dark);
|
|
}
|
|
|
|
/* Dashboard */
|
|
.dashboard-header {
|
|
margin-bottom: 24px;
|
|
}
|
|
.dashboard-header h1 {
|
|
font-size: 1.6rem;
|
|
margin-bottom: 4px;
|
|
}
|
|
.dashboard-header p {
|
|
color: var(--gray);
|
|
}
|
|
|
|
.stats-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
gap: 16px;
|
|
margin-bottom: 28px;
|
|
}
|
|
.stat-card {
|
|
background: var(--white);
|
|
border-radius: var(--radius);
|
|
padding: 20px;
|
|
box-shadow: var(--shadow);
|
|
text-align: center;
|
|
}
|
|
.stat-card .stat-value {
|
|
font-size: 1.6rem;
|
|
font-weight: 700;
|
|
color: var(--green);
|
|
}
|
|
.stat-card .stat-label {
|
|
color: var(--gray);
|
|
font-size: 0.85rem;
|
|
margin-top: 4px;
|
|
}
|
|
.stat-card .stat-sub {
|
|
font-size: 0.75rem;
|
|
color: var(--gray);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.badge {
|
|
display: inline-block;
|
|
padding: 2px 10px;
|
|
border-radius: 20px;
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
}
|
|
.badge-green { background: rgba(46,204,113,0.15); color: var(--green-dark); }
|
|
.badge-blue { background: rgba(52,152,219,0.15); color: var(--blue); }
|
|
.badge-orange { background: rgba(243,156,18,0.15); color: var(--orange); }
|
|
.badge-red { background: rgba(231,76,60,0.15); color: var(--red); }
|
|
.badge-purple { background: rgba(155,89,182,0.15); color: var(--purple); }
|
|
.badge-yellow { background: rgba(241,196,15,0.2); color: #d68910; }
|
|
|
|
/* Tabs */
|
|
.tabs {
|
|
display: flex;
|
|
background: var(--white);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
margin-bottom: 24px;
|
|
overflow-x: auto;
|
|
}
|
|
.tab-btn {
|
|
flex: 1;
|
|
padding: 14px 20px;
|
|
border: none;
|
|
background: none;
|
|
cursor: pointer;
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
color: var(--gray);
|
|
transition: all 0.2s;
|
|
white-space: nowrap;
|
|
border-bottom: 3px solid transparent;
|
|
}
|
|
.tab-btn:hover { color: var(--dark); }
|
|
.tab-btn.active {
|
|
color: var(--green);
|
|
border-bottom-color: var(--green);
|
|
background: rgba(46, 204, 113, 0.05);
|
|
}
|
|
|
|
/* Week selector */
|
|
.week-selector {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin-bottom: 16px;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
}
|
|
.week-selector .label {
|
|
font-weight: 600;
|
|
color: var(--dark-light);
|
|
margin-right: 4px;
|
|
}
|
|
.week-btn {
|
|
padding: 8px 18px;
|
|
border: 2px solid var(--gray-light);
|
|
border-radius: 8px;
|
|
background: var(--white);
|
|
cursor: pointer;
|
|
font-size: 0.85rem;
|
|
font-weight: 600;
|
|
color: var(--dark-light);
|
|
transition: all 0.2s;
|
|
}
|
|
.week-btn:hover { border-color: var(--green); color: var(--green); }
|
|
.week-btn.active {
|
|
background: var(--green);
|
|
color: var(--white);
|
|
border-color: var(--green);
|
|
}
|
|
|
|
/* Content cards */
|
|
.content-card {
|
|
background: var(--white);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
padding: 24px;
|
|
margin-bottom: 20px;
|
|
}
|
|
.content-card h3 {
|
|
margin-bottom: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
/* Warning box */
|
|
.warning-box {
|
|
background: #fef9e7;
|
|
border-left: 4px solid var(--orange);
|
|
border-radius: 8px;
|
|
padding: 14px 18px;
|
|
margin-bottom: 16px;
|
|
font-size: 0.9rem;
|
|
color: #7d6608;
|
|
}
|
|
|
|
/* Workout day card */
|
|
.day-card {
|
|
background: var(--white);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
margin-bottom: 16px;
|
|
overflow: hidden;
|
|
}
|
|
.day-header {
|
|
padding: 16px 20px;
|
|
background: var(--dark);
|
|
color: var(--white);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
}
|
|
.day-header h3 { margin: 0; font-size: 1.05rem; }
|
|
.day-header .day-meta {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.day-header .day-duration {
|
|
font-size: 0.8rem;
|
|
color: var(--gray-light);
|
|
}
|
|
.day-header .badge {
|
|
padding: 4px 12px;
|
|
border-radius: 20px;
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
}
|
|
.badge-strength { background: var(--red); }
|
|
.badge-cardio { background: var(--orange); }
|
|
.badge-rest { background: var(--blue); }
|
|
.badge-flexibility { background: var(--purple); }
|
|
.badge-active_recovery { background: #1abc9c; }
|
|
.badge-light_activity { background: #1abc9c; }
|
|
.day-body {
|
|
padding: 0;
|
|
max-height: 0;
|
|
overflow: hidden;
|
|
transition: max-height 0.3s ease, padding 0.3s ease;
|
|
}
|
|
.day-body.open {
|
|
max-height: 8000px;
|
|
padding: 16px 20px;
|
|
}
|
|
|
|
/* Warmup/Cooldown section */
|
|
.routine-section {
|
|
background: var(--light);
|
|
border-radius: 8px;
|
|
padding: 14px;
|
|
margin-bottom: 14px;
|
|
}
|
|
.routine-section h4 {
|
|
font-size: 0.9rem;
|
|
margin-bottom: 10px;
|
|
color: var(--dark-light);
|
|
}
|
|
.routine-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 6px 0;
|
|
font-size: 0.85rem;
|
|
border-bottom: 1px solid rgba(0,0,0,0.05);
|
|
}
|
|
.routine-item:last-child { border-bottom: none; }
|
|
.routine-item .routine-name { font-weight: 500; }
|
|
.routine-item .routine-dur {
|
|
color: var(--green-dark);
|
|
font-weight: 600;
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
/* Exercise cards with GIF */
|
|
.exercise-card {
|
|
background: var(--light);
|
|
border-radius: 8px;
|
|
padding: 14px;
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
gap: 14px;
|
|
align-items: flex-start;
|
|
}
|
|
.exercise-card:last-child { margin-bottom: 0; }
|
|
.exercise-gif {
|
|
width: 200px;
|
|
height: 150px;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
background: #dfe6e9;
|
|
flex-shrink: 0;
|
|
}
|
|
.exercise-gif img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
border-radius: 8px;
|
|
}
|
|
.gif-placeholder {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--gray);
|
|
font-size: 0.8rem;
|
|
}
|
|
.gif-placeholder .gif-icon {
|
|
font-size: 2rem;
|
|
margin-bottom: 4px;
|
|
}
|
|
.exercise-details { flex: 1; min-width: 0; }
|
|
.exercise-details .ex-name {
|
|
font-weight: 600;
|
|
font-size: 0.95rem;
|
|
margin-bottom: 6px;
|
|
}
|
|
.exercise-details .ex-meta {
|
|
display: flex;
|
|
gap: 8px;
|
|
flex-wrap: wrap;
|
|
font-size: 0.8rem;
|
|
margin-bottom: 6px;
|
|
}
|
|
.exercise-details .ex-tag {
|
|
padding: 2px 8px;
|
|
background: var(--white);
|
|
border-radius: 4px;
|
|
font-weight: 600;
|
|
}
|
|
.exercise-details .ex-muscle {
|
|
padding: 2px 8px;
|
|
background: rgba(46,204,113,0.12);
|
|
border-radius: 4px;
|
|
font-weight: 600;
|
|
color: var(--green-dark);
|
|
font-size: 0.75rem;
|
|
}
|
|
.exercise-details .ex-equipment {
|
|
padding: 2px 8px;
|
|
background: rgba(52,152,219,0.12);
|
|
border-radius: 4px;
|
|
font-weight: 600;
|
|
color: var(--blue);
|
|
font-size: 0.75rem;
|
|
}
|
|
.exercise-details .ex-instructions {
|
|
font-size: 0.8rem;
|
|
color: var(--dark-light);
|
|
margin-top: 6px;
|
|
padding-left: 16px;
|
|
}
|
|
.exercise-details .ex-instructions li {
|
|
margin-bottom: 2px;
|
|
}
|
|
.exercise-details .ex-notes {
|
|
font-size: 0.8rem;
|
|
color: var(--gray);
|
|
font-style: italic;
|
|
margin-top: 4px;
|
|
}
|
|
.exercise-details .ex-alternatives {
|
|
font-size: 0.78rem;
|
|
color: var(--blue);
|
|
margin-top: 4px;
|
|
}
|
|
|
|
/* Meal plan */
|
|
.meal-day-card {
|
|
background: var(--white);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
margin-bottom: 16px;
|
|
overflow: hidden;
|
|
}
|
|
.meal-day-header {
|
|
padding: 16px 20px;
|
|
background: var(--green-dark);
|
|
color: var(--white);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
}
|
|
.meal-day-header h3 { margin: 0; font-size: 1.05rem; }
|
|
.meal-day-body {
|
|
padding: 0;
|
|
max-height: 0;
|
|
overflow: hidden;
|
|
transition: max-height 0.3s ease, padding 0.3s ease;
|
|
}
|
|
.meal-day-body.open {
|
|
max-height: 5000px;
|
|
padding: 16px 20px;
|
|
}
|
|
.meal-item {
|
|
background: var(--light);
|
|
border-radius: 8px;
|
|
padding: 14px;
|
|
margin-bottom: 12px;
|
|
}
|
|
.meal-item:last-child { margin-bottom: 0; }
|
|
.meal-type {
|
|
font-size: 0.75rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
color: var(--green-dark);
|
|
margin-bottom: 4px;
|
|
}
|
|
.meal-name {
|
|
font-weight: 600;
|
|
font-size: 1rem;
|
|
margin-bottom: 8px;
|
|
}
|
|
.meal-macros {
|
|
display: flex;
|
|
gap: 8px;
|
|
flex-wrap: wrap;
|
|
margin-bottom: 8px;
|
|
}
|
|
.macro-tag {
|
|
font-size: 0.75rem;
|
|
padding: 2px 8px;
|
|
border-radius: 4px;
|
|
font-weight: 600;
|
|
}
|
|
.macro-cal { background: #ffeaa7; color: #d68910; }
|
|
.macro-pro { background: #dfe6e9; color: var(--dark); }
|
|
.macro-carb { background: #dfe6e9; color: var(--dark); }
|
|
.macro-fat { background: #dfe6e9; color: var(--dark); }
|
|
.macro-fiber { background: #d5f5e3; color: var(--green-dark); }
|
|
.meal-ingredients {
|
|
font-size: 0.85rem;
|
|
color: var(--dark-light);
|
|
}
|
|
.meal-ingredients span {
|
|
display: inline-block;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
/* Body metrics card */
|
|
.metrics-card {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
gap: 12px;
|
|
margin-bottom: 16px;
|
|
}
|
|
.metric-item {
|
|
text-align: center;
|
|
padding: 12px;
|
|
background: var(--light);
|
|
border-radius: 8px;
|
|
}
|
|
.metric-item .metric-value {
|
|
font-size: 1.3rem;
|
|
font-weight: 700;
|
|
color: var(--dark);
|
|
}
|
|
.metric-item .metric-label {
|
|
font-size: 0.8rem;
|
|
color: var(--gray);
|
|
}
|
|
|
|
/* Supplement card */
|
|
.supplement-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
padding: 10px 0;
|
|
border-bottom: 1px solid var(--light);
|
|
}
|
|
.supplement-item:last-child { border-bottom: none; }
|
|
.supplement-name { font-weight: 600; }
|
|
.supplement-dosage { font-size: 0.85rem; color: var(--gray); }
|
|
.supplement-reason { font-size: 0.8rem; color: var(--green-dark); }
|
|
|
|
/* Shopping list */
|
|
.shopping-category { margin-bottom: 20px; }
|
|
.shopping-category h4 {
|
|
font-size: 1rem;
|
|
margin-bottom: 10px;
|
|
padding-bottom: 6px;
|
|
border-bottom: 2px solid var(--green);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.shopping-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 8px 12px;
|
|
border-radius: 6px;
|
|
margin-bottom: 4px;
|
|
}
|
|
.shopping-item:nth-child(even) { background: var(--light); }
|
|
.shopping-item .item-name { font-weight: 500; }
|
|
.shopping-item .item-amount {
|
|
color: var(--gray);
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Tips */
|
|
.tips-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
}
|
|
.tips-list li {
|
|
padding: 8px 0 8px 24px;
|
|
position: relative;
|
|
font-size: 0.9rem;
|
|
}
|
|
.tips-list li::before {
|
|
content: "\2713";
|
|
position: absolute;
|
|
left: 0;
|
|
color: var(--green);
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* Loading spinner */
|
|
.loading {
|
|
text-align: center;
|
|
padding: 40px;
|
|
color: var(--gray);
|
|
}
|
|
.spinner {
|
|
width: 40px;
|
|
height: 40px;
|
|
border: 4px solid var(--gray-light);
|
|
border-top-color: var(--green);
|
|
border-radius: 50%;
|
|
animation: spin 0.8s linear infinite;
|
|
margin: 0 auto 16px;
|
|
}
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
|
|
/* Print styles */
|
|
@media print {
|
|
.navbar, .tabs, .btn, .step-indicator, .step-buttons, .week-selector, .toggle-switch { display: none !important; }
|
|
.day-body, .meal-day-body { max-height: none !important; padding: 16px 20px !important; }
|
|
.content-card, .day-card, .meal-day-card { box-shadow: none; break-inside: avoid; }
|
|
body { background: white; }
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 768px) {
|
|
.form-row { grid-template-columns: 1fr; }
|
|
.form-row-3 { grid-template-columns: 1fr; }
|
|
.stats-grid { grid-template-columns: 1fr 1fr; }
|
|
.auth-card { padding: 24px; }
|
|
.profile-setup { padding: 24px; margin: 16px; }
|
|
.container { padding: 12px; }
|
|
.tabs { border-radius: 8px; }
|
|
.tab-btn { padding: 10px 12px; font-size: 0.8rem; }
|
|
.radio-group { flex-direction: column; gap: 8px; }
|
|
.metrics-card { grid-template-columns: 1fr 1fr; }
|
|
.location-cards { grid-template-columns: 1fr; }
|
|
.exercise-card { flex-direction: column; }
|
|
.exercise-gif { width: 100%; height: 180px; }
|
|
.checkbox-group { gap: 6px; }
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.stats-grid { grid-template-columns: 1fr; }
|
|
.meal-macros { gap: 6px; }
|
|
.week-selector { gap: 4px; }
|
|
.week-btn { padding: 6px 12px; font-size: 0.8rem; }
|
|
.exercise-gif { height: 140px; }
|
|
}
|
|
|
|
.hidden { display: none !important; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Navbar -->
|
|
<nav class="navbar" id="navbar">
|
|
<div class="brand">FitLife <span>Saglik & Fitness</span></div>
|
|
<div class="user-info" id="navUserInfo" style="display:none;">
|
|
<span class="user-name" id="navUserName"></span>
|
|
<button class="btn btn-sm btn-danger" onclick="logout()">Cikis</button>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- AUTH: Login -->
|
|
<div id="loginPage" class="auth-page">
|
|
<div class="auth-card">
|
|
<h2>Giris Yap</h2>
|
|
<p class="subtitle">Hesabiniza giris yapin</p>
|
|
<div id="loginError" class="error-msg" style="display:none;"></div>
|
|
<form onsubmit="handleLogin(event)">
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="loginEmail" required placeholder="ornek@email.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Sifre</label>
|
|
<input type="password" id="loginPassword" required placeholder="Sifrenizi girin" minlength="6">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-lg" style="width:100%;" id="loginBtn">Giris Yap</button>
|
|
</form>
|
|
<p class="link-text">Hesabiniz yok mu? <a onclick="showPage('register')">Kayit Olun</a></p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- AUTH: Register -->
|
|
<div id="registerPage" class="auth-page hidden">
|
|
<div class="auth-card">
|
|
<h2>Kayit Ol</h2>
|
|
<p class="subtitle">Yeni hesap olusturun</p>
|
|
<div id="registerError" class="error-msg" style="display:none;"></div>
|
|
<form onsubmit="handleRegister(event)">
|
|
<div class="form-group">
|
|
<label>Ad Soyad</label>
|
|
<input type="text" id="regName" required placeholder="Adiniz Soyadiniz">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="regEmail" required placeholder="ornek@email.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Sifre</label>
|
|
<input type="password" id="regPassword" required placeholder="En az 6 karakter" minlength="6">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-lg" style="width:100%;" id="regBtn">Kayit Ol</button>
|
|
</form>
|
|
<p class="link-text">Zaten hesabiniz var mi? <a onclick="showPage('login')">Giris Yapin</a></p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- PROFILE SETUP -->
|
|
<div id="profilePage" class="hidden">
|
|
<div class="profile-setup">
|
|
<h2>Profil Bilgileri</h2>
|
|
<p class="subtitle">Size ozel program icin bilgilerinizi girin</p>
|
|
|
|
<div class="progress-bar-container">
|
|
<div class="progress-bar-fill" id="progressBarFill" style="width:14.3%;"></div>
|
|
</div>
|
|
<div class="step-indicator" id="stepIndicator">
|
|
<div class="step-dot active" data-step="1"></div>
|
|
<div class="step-dot" data-step="2"></div>
|
|
<div class="step-dot" data-step="3"></div>
|
|
<div class="step-dot" data-step="4"></div>
|
|
<div class="step-dot" data-step="5"></div>
|
|
<div class="step-dot" data-step="6"></div>
|
|
<div class="step-dot" data-step="7"></div>
|
|
</div>
|
|
<div class="step-label" id="stepLabel">Adim 1/7 - Temel Bilgiler</div>
|
|
<div id="profileError" class="error-msg" style="display:none;"></div>
|
|
|
|
<!-- Step 1: Temel Bilgiler -->
|
|
<div id="profileStep1">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Yas</label>
|
|
<input type="number" id="profAge" min="15" max="80" required placeholder="25">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Cinsiyet</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="profGender" value="male">
|
|
<span>Erkek</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="profGender" value="female">
|
|
<span>Kadin</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Boy (cm)</label>
|
|
<input type="number" id="profHeight" min="100" max="250" required placeholder="175">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Kilo (kg)</label>
|
|
<input type="number" id="profWeight" min="30" max="300" step="0.1" required placeholder="75">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Hedef Kilo (kg)</label>
|
|
<input type="number" id="profTargetWeight" min="30" max="300" step="0.1" placeholder="70">
|
|
</div>
|
|
<div class="step-buttons">
|
|
<span></span>
|
|
<button class="btn btn-primary" onclick="profileNextStep(2)">Devam Et</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 2: Vucut Olculeri (opsiyonel) -->
|
|
<div id="profileStep2" class="hidden">
|
|
<p style="color:var(--gray);font-size:0.85rem;margin-bottom:16px;">Bu adim opsiyoneldir. Daha hassas hesaplama icin doldurun.</p>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Vucut Yag Orani (%)</label>
|
|
<input type="number" id="profBodyFat" min="3" max="60" step="0.1" placeholder="orn: 20">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Bel Cevresi (cm)</label>
|
|
<input type="number" id="profWaist" min="40" max="200" step="0.1" placeholder="orn: 80">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Kalca Cevresi (cm)</label>
|
|
<input type="number" id="profHip" min="50" max="200" step="0.1" placeholder="orn: 95">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Boyun Cevresi (cm)</label>
|
|
<input type="number" id="profNeck" min="20" max="60" step="0.1" placeholder="orn: 38">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Bilek Cevresi (cm)</label>
|
|
<input type="number" id="profWrist" min="10" max="30" step="0.1" placeholder="orn: 17">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Gogus Cevresi (cm)</label>
|
|
<input type="number" id="profChest" min="50" max="200" step="0.1" placeholder="orn: 95">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Kol Cevresi (cm)</label>
|
|
<input type="number" id="profArm" min="15" max="60" step="0.1" placeholder="orn: 32">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Uyluk Cevresi (cm)</label>
|
|
<input type="number" id="profThigh" min="30" max="100" step="0.1" placeholder="orn: 55">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Baldir Cevresi (cm)</label>
|
|
<input type="number" id="profCalf" min="20" max="60" step="0.1" placeholder="orn: 37">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Vucut Tipi</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="bodyType" value="ectomorph">
|
|
<span>Ectomorph<span class="radio-desc">Ince yapili, zor kilo alir</span></span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="bodyType" value="mesomorph">
|
|
<span>Mesomorph<span class="radio-desc">Atletik yapili, kolay kas yapar</span></span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="bodyType" value="endomorph">
|
|
<span>Endomorph<span class="radio-desc">Genis yapili, kolay kilo alir</span></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="step-buttons">
|
|
<button class="btn btn-secondary" onclick="profileNextStep(1)">Geri</button>
|
|
<button class="btn btn-primary" onclick="profileNextStep(3)">Devam Et</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 3: Yasam Tarzi -->
|
|
<div id="profileStep3" class="hidden">
|
|
<div class="form-group">
|
|
<label>Hedef <span class="hint">(birden fazla secilebilir)</span></label>
|
|
<div class="checkbox-group">
|
|
<label>
|
|
<input type="checkbox" name="profGoal" value="lose_weight">
|
|
<span>Kilo Vermek</span>
|
|
</label>
|
|
<label>
|
|
<input type="checkbox" name="profGoal" value="gain_weight">
|
|
<span>Kilo Almak</span>
|
|
</label>
|
|
<label>
|
|
<input type="checkbox" name="profGoal" value="build_muscle">
|
|
<span>Kas Gelistirmek</span>
|
|
</label>
|
|
<label>
|
|
<input type="checkbox" name="profGoal" value="maintain">
|
|
<span>Formu Korumak</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Aktivite Seviyesi <span class="hint">(birden fazla secilebilir)</span></label>
|
|
<div class="checkbox-group">
|
|
<label>
|
|
<input type="checkbox" name="profActivity" value="sedentary">
|
|
<span>Hareketsiz<span class="radio-desc">Masa basi is, az hareket</span></span>
|
|
</label>
|
|
<label>
|
|
<input type="checkbox" name="profActivity" value="light">
|
|
<span>Hafif<span class="radio-desc">Haftada 1-2 gun hafif egzersiz</span></span>
|
|
</label>
|
|
<label>
|
|
<input type="checkbox" name="profActivity" value="moderate">
|
|
<span>Orta<span class="radio-desc">Haftada 3-5 gun egzersiz</span></span>
|
|
</label>
|
|
<label>
|
|
<input type="checkbox" name="profActivity" value="active">
|
|
<span>Aktif<span class="radio-desc">Haftada 6-7 gun egzersiz</span></span>
|
|
</label>
|
|
<label>
|
|
<input type="checkbox" name="profActivity" value="very_active">
|
|
<span>Cok Aktif<span class="radio-desc">Gunde 2 antrenman veya agir fiziksel is</span></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Is Turu</label>
|
|
<select id="profJobType">
|
|
<option value="">Seciniz</option>
|
|
<option value="desk">Masa Basi</option>
|
|
<option value="standing">Ayakta</option>
|
|
<option value="physical">Fiziksel</option>
|
|
<option value="mixed">Karisik</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Gunluk Uyku Saati</label>
|
|
<input type="number" id="profSleep" min="3" max="12" step="0.5" placeholder="7">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Uyku Kalitesi</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="sleepQuality" value="poor">
|
|
<span>Kotu</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="sleepQuality" value="moderate">
|
|
<span>Orta</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="sleepQuality" value="good">
|
|
<span>Iyi</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Gunluk Su Tuketimi (litre)</label>
|
|
<input type="number" id="profWater" min="0" max="10" step="0.1" placeholder="2.0">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Stres Seviyesi</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="stressLevel" value="low">
|
|
<span>Dusuk</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="stressLevel" value="medium">
|
|
<span>Orta</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="stressLevel" value="high">
|
|
<span>Yuksek</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Tahmini Gunluk Adim Sayisi</label>
|
|
<input type="number" id="profDailySteps" min="0" max="50000" step="500" placeholder="5000">
|
|
</div>
|
|
</div>
|
|
<div class="step-buttons">
|
|
<button class="btn btn-secondary" onclick="profileNextStep(2)">Geri</button>
|
|
<button class="btn btn-primary" onclick="profileNextStep(4)">Devam Et</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 4: Antrenman Tercihleri -->
|
|
<div id="profileStep4" class="hidden">
|
|
<div class="form-group">
|
|
<label>Antrenman Yeri</label>
|
|
<div class="location-cards">
|
|
<div class="location-card" data-value="gym" onclick="selectLocation('gym')">
|
|
<div class="loc-icon">🏋️</div>
|
|
<div class="loc-title">Spor Salonu</div>
|
|
<div class="loc-desc">Tam ekipman erisimi</div>
|
|
</div>
|
|
<div class="location-card" data-value="home" onclick="selectLocation('home')">
|
|
<div class="loc-icon">🏠</div>
|
|
<div class="loc-title">Ev</div>
|
|
<div class="loc-desc">Sinirli ekipman</div>
|
|
</div>
|
|
<div class="location-card" data-value="none" onclick="selectLocation('none')">
|
|
<div class="loc-icon">❌</div>
|
|
<div class="loc-title">Egzersiz Yapamiyorum</div>
|
|
<div class="loc-desc">Saglik/hareket kisitlamasi</div>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" id="profWorkoutLocation" value="">
|
|
</div>
|
|
|
|
<!-- Gym fields -->
|
|
<div id="gymFields" class="hidden">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Antrenman Deneyimi</label>
|
|
<select id="profExperience">
|
|
<option value="">Seciniz</option>
|
|
<option value="beginner">Baslangic</option>
|
|
<option value="intermediate">Orta Seviye</option>
|
|
<option value="advanced">Ileri Seviye</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Haftada Antrenman Gunu</label>
|
|
<input type="number" id="profWorkoutDays" min="1" max="7" placeholder="4">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Antrenman Suresi (dakika)</label>
|
|
<input type="number" id="profWorkoutDuration" min="15" max="180" placeholder="60">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Fitness Hedefi <span class="hint">(birden fazla secilebilir)</span></label>
|
|
<div class="checkbox-group">
|
|
<label><input type="checkbox" name="profFitnessGoal" value="strength"><span>Kuvvet</span></label>
|
|
<label><input type="checkbox" name="profFitnessGoal" value="hypertrophy"><span>Kas Buyumesi</span></label>
|
|
<label><input type="checkbox" name="profFitnessGoal" value="endurance"><span>Dayaniklilik</span></label>
|
|
<label><input type="checkbox" name="profFitnessGoal" value="general"><span>Genel Fitness</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Kardiyo Tercihi <span class="hint">(birden fazla secilebilir)</span></label>
|
|
<div class="checkbox-group">
|
|
<label><input type="checkbox" name="profCardioPreference" value="running"><span>Kosma</span></label>
|
|
<label><input type="checkbox" name="profCardioPreference" value="cycling"><span>Bisiklet</span></label>
|
|
<label><input type="checkbox" name="profCardioPreference" value="swimming"><span>Yuzme</span></label>
|
|
<label><input type="checkbox" name="profCardioPreference" value="rowing"><span>Kure</span></label>
|
|
<label><input type="checkbox" name="profCardioPreference" value="elliptical"><span>Eliptik</span></label>
|
|
<label><input type="checkbox" name="profCardioPreference" value="none"><span>Kardiyo Yapmak Istemiyorum</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Home fields -->
|
|
<div id="homeFields" class="hidden">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Antrenman Deneyimi</label>
|
|
<select id="profExperienceHome">
|
|
<option value="">Seciniz</option>
|
|
<option value="beginner">Baslangic</option>
|
|
<option value="intermediate">Orta Seviye</option>
|
|
<option value="advanced">Ileri Seviye</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Haftada Antrenman Gunu</label>
|
|
<input type="number" id="profWorkoutDaysHome" min="1" max="7" placeholder="3">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Antrenman Suresi (dakika)</label>
|
|
<input type="number" id="profWorkoutDurationHome" min="15" max="120" placeholder="45">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Ekipmaniniz var mi?</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="profHasEquipment" onchange="toggleEquipmentFields()">
|
|
<div class="toggle-slider"></div>
|
|
<span style="font-weight:500;">Evet, ekipmanim var</span>
|
|
</label>
|
|
</div>
|
|
<div id="equipmentFields" class="hidden">
|
|
<div class="form-group">
|
|
<label>Mevcut Ekipmanlar</label>
|
|
<div class="checkbox-group">
|
|
<label><input type="checkbox" name="equipment" value="dumbbells"><span>Dambil</span></label>
|
|
<label><input type="checkbox" name="equipment" value="resistance_bands"><span>Direnk Bandi</span></label>
|
|
<label><input type="checkbox" name="equipment" value="pull_up_bar"><span>Baris</span></label>
|
|
<label><input type="checkbox" name="equipment" value="yoga_mat"><span>Yoga Mati</span></label>
|
|
<label><input type="checkbox" name="equipment" value="kettlebell"><span>Kettlebell</span></label>
|
|
<label><input type="checkbox" name="equipment" value="jump_rope"><span>Atlama Ipi</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- None fields -->
|
|
<div id="noneFields" class="hidden">
|
|
<div class="info-box">
|
|
Saglik profilinize gore size uygun hafif gunluk aktivite plani olusturacagiz. Yuruyus, nefes egzersizleri ve hafif esneme hareketleri icerebilir.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="step-buttons">
|
|
<button class="btn btn-secondary" onclick="profileNextStep(3)">Geri</button>
|
|
<button class="btn btn-primary" onclick="profileNextStep(5)">Devam Et</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 5: Sakatlik & Engellilik -->
|
|
<div id="profileStep5" class="hidden">
|
|
<!-- Injury -->
|
|
<div class="form-group">
|
|
<label>Sakatlik var mi?</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="profHasInjury" onchange="toggleInjuryFields()">
|
|
<div class="toggle-slider"></div>
|
|
<span style="font-weight:500;">Evet, sakatligim var</span>
|
|
</label>
|
|
</div>
|
|
<div id="injuryFields" class="cond-fields hidden">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Sakatlik Bolgesi <span class="hint">(birden fazla secilebilir)</span></label>
|
|
<div class="checkbox-group">
|
|
<label><input type="checkbox" name="profInjuryArea" value="knee"><span>Diz</span></label>
|
|
<label><input type="checkbox" name="profInjuryArea" value="back"><span>Sirt / Bel</span></label>
|
|
<label><input type="checkbox" name="profInjuryArea" value="shoulder"><span>Omuz</span></label>
|
|
<label><input type="checkbox" name="profInjuryArea" value="elbow"><span>Dirsek</span></label>
|
|
<label><input type="checkbox" name="profInjuryArea" value="wrist"><span>Bilek</span></label>
|
|
<label><input type="checkbox" name="profInjuryArea" value="ankle"><span>Ayak Bilegi</span></label>
|
|
<label><input type="checkbox" name="profInjuryArea" value="hip"><span>Kalca</span></label>
|
|
<label><input type="checkbox" name="profInjuryArea" value="neck"><span>Boyun</span></label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Sakatlik Siddeti</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="injurySeverity" value="mild">
|
|
<span>Hafif</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="injurySeverity" value="moderate">
|
|
<span>Orta</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="injurySeverity" value="severe">
|
|
<span>Agir</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Sakatlik Notlari</label>
|
|
<textarea id="profInjuryNotes" placeholder="Sakatliginiz hakkinda ek bilgi..."></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Disability -->
|
|
<div class="form-group" style="margin-top:20px;">
|
|
<label>Engellilik durumu var mi?</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="profHasDisability" onchange="toggleDisabilityFields()">
|
|
<div class="toggle-slider"></div>
|
|
<span style="font-weight:500;">Evet, engellilik durumum var</span>
|
|
</label>
|
|
</div>
|
|
<div id="disabilityFields" class="cond-fields-blue hidden">
|
|
<div class="form-group">
|
|
<label>Engellilik Turu</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="disabilityType" value="visual">
|
|
<span>Gorme</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="disabilityType" value="hearing">
|
|
<span>Isitme</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="disabilityType" value="motor">
|
|
<span>Motor</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="disabilityType" value="cognitive">
|
|
<span>Bilissel</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="disabilityType" value="multiple">
|
|
<span>Birden Fazla</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Detaylar</label>
|
|
<textarea id="profDisabilityDetails" placeholder="Engellilik durumunuz hakkinda detay..."></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Hareket Kabiliyeti</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="mobilityLevel" value="full">
|
|
<span>Tam</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="mobilityLevel" value="limited_upper">
|
|
<span>Ust Vucut Sinirli</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="mobilityLevel" value="limited_lower">
|
|
<span>Alt Vucut Sinirli</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="mobilityLevel" value="limited_both">
|
|
<span>Her Iki Taraf Sinirli</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="mobilityLevel" value="wheelchair">
|
|
<span>Tekerlekli Sandalye</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="mobilityLevel" value="bedbound">
|
|
<span>Yatak Bagimlisi</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Tekerlekli sandalye kullaniyor musunuz?</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="profUsesWheelchair">
|
|
<div class="toggle-slider"></div>
|
|
<span style="font-weight:500;">Evet</span>
|
|
</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Protez kullaniyor musunuz?</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="profHasProsthetic" onchange="toggleProstheticFields()">
|
|
<div class="toggle-slider"></div>
|
|
<span style="font-weight:500;">Evet</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div id="prostheticFields" class="hidden">
|
|
<div class="form-group">
|
|
<label>Protez Bolgesi</label>
|
|
<input type="text" id="profProstheticArea" placeholder="orn: Sol bacak, sag kol">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="step-buttons">
|
|
<button class="btn btn-secondary" onclick="profileNextStep(4)">Geri</button>
|
|
<button class="btn btn-primary" onclick="profileNextStep(6)">Devam Et</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 6: Tibbi Gecmis -->
|
|
<div id="profileStep6" class="hidden">
|
|
<p style="color:var(--gray);font-size:0.85rem;margin-bottom:16px;">Saglik durumunuz program olusturmada dikkate alinir. Bu bilgiler gizli tutulur.</p>
|
|
|
|
<!-- Condition toggles -->
|
|
<div class="form-group">
|
|
<label style="margin-bottom:12px;">Kronik Hastaliklar</label>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Kalp Hastaligi</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHeartCondition" onchange="toggleMedField('heartDetail')">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
<div id="heartDetail" class="medical-detail-fields hidden">
|
|
<div class="form-group" style="margin-bottom:0;">
|
|
<label>Kalp Hastaligi Detayi</label>
|
|
<input type="text" id="profHeartConditionDetails" placeholder="orn: Kapak yetersizligi, aritmi...">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Diyabet</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHasDiabetes" onchange="toggleMedField('diabetesDetail')">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
<div id="diabetesDetail" class="medical-detail-fields hidden">
|
|
<div class="form-group" style="margin-bottom:0;">
|
|
<label>Diyabet Turu</label>
|
|
<div class="radio-group">
|
|
<label><input type="radio" name="diabetesType" value="type1"><span>Tip 1</span></label>
|
|
<label><input type="radio" name="diabetesType" value="type2"><span>Tip 2</span></label>
|
|
<label><input type="radio" name="diabetesType" value="gestational"><span>Gestasyonel</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Tiroid</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHasThyroid" onchange="toggleMedField('thyroidDetail')">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
<div id="thyroidDetail" class="medical-detail-fields hidden">
|
|
<div class="form-group" style="margin-bottom:0;">
|
|
<label>Tiroid Turu</label>
|
|
<div class="radio-group">
|
|
<label><input type="radio" name="thyroidType" value="hypo"><span>Hipotiroid</span></label>
|
|
<label><input type="radio" name="thyroidType" value="hyper"><span>Hipertiroid</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Astim</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHasAsthma">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Epilepsi</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHasEpilepsy">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Artrit (Eklem Iltihaplanmasi)</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHasArthritis" onchange="toggleMedField('arthritisDetail')">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
<div id="arthritisDetail" class="medical-detail-fields hidden">
|
|
<div class="form-group" style="margin-bottom:0;">
|
|
<label>Artrit Turu</label>
|
|
<div class="radio-group">
|
|
<label><input type="radio" name="arthritisType" value="rheumatoid"><span>Romatoid</span></label>
|
|
<label><input type="radio" name="arthritisType" value="osteo"><span>Osteoartrit</span></label>
|
|
<label><input type="radio" name="arthritisType" value="psoriatic"><span>Psoriatik</span></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Osteoporoz</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHasOsteoporosis">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="medical-toggle-row">
|
|
<span class="med-label">Fibromiyalji</span>
|
|
<label class="toggle-switch" style="margin:0;">
|
|
<input type="checkbox" id="profHasFibromyalgia">
|
|
<div class="toggle-slider"></div>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Blood & vitals -->
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Kan Grubu</label>
|
|
<select id="profBloodType">
|
|
<option value="">Seciniz</option>
|
|
<option value="A+">A Rh+</option>
|
|
<option value="A-">A Rh-</option>
|
|
<option value="B+">B Rh+</option>
|
|
<option value="B-">B Rh-</option>
|
|
<option value="AB+">AB Rh+</option>
|
|
<option value="AB-">AB Rh-</option>
|
|
<option value="O+">0 Rh+</option>
|
|
<option value="O-">0 Rh-</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Tansiyon</label>
|
|
<select id="profBloodPressure">
|
|
<option value="">Seciniz</option>
|
|
<option value="normal">Normal</option>
|
|
<option value="low">Dusuk</option>
|
|
<option value="elevated">Yukselmis</option>
|
|
<option value="high">Yuksek</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Kan Sekeri</label>
|
|
<select id="profBloodSugar">
|
|
<option value="">Seciniz</option>
|
|
<option value="normal">Normal</option>
|
|
<option value="low">Dusuk</option>
|
|
<option value="pre_diabetic">Pre-diyabetik</option>
|
|
<option value="high">Yuksek</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Kolesterol</label>
|
|
<select id="profCholesterol">
|
|
<option value="">Seciniz</option>
|
|
<option value="normal">Normal</option>
|
|
<option value="borderline">Sinirda</option>
|
|
<option value="high">Yuksek</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Ruh Sagligi</label>
|
|
<select id="profMentalHealth">
|
|
<option value="none">Yok</option>
|
|
<option value="anxiety">Anksiyete</option>
|
|
<option value="depression">Depresyon</option>
|
|
<option value="both">Her Ikisi</option>
|
|
<option value="other">Diger</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Text fields -->
|
|
<div class="form-group">
|
|
<label>Diger Saglik Sorunlari</label>
|
|
<textarea id="profHealthConditions" placeholder="Varsa diger saglik sorunlariniz..."></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Kronik Hastaliklar (Diger)</label>
|
|
<textarea id="profChronicDiseases" placeholder="Yukaridakiler haricinde varsa..."></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Kullanilan Ilaclar</label>
|
|
<textarea id="profMedications" placeholder="Duzeni olarak kullandiginiz ilaclar..."></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Gecmis Ameliyatlar</label>
|
|
<textarea id="profSurgeries" placeholder="Gecirdiginiz ameliyatlar..."></textarea>
|
|
</div>
|
|
|
|
<div class="step-buttons">
|
|
<button class="btn btn-secondary" onclick="profileNextStep(5)">Geri</button>
|
|
<button class="btn btn-primary" onclick="profileNextStep(7)">Devam Et</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 7: Beslenme Tercihleri -->
|
|
<div id="profileStep7" class="hidden">
|
|
<div class="form-group">
|
|
<label>Gunluk Ogun Sayisi: <span id="mealsValue">5</span></label>
|
|
<input type="range" id="profMeals" min="2" max="8" value="5" style="width:100%;" oninput="document.getElementById('mealsValue').textContent=this.value">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Alerjiler</label>
|
|
<div class="checkbox-group">
|
|
<label><input type="checkbox" name="allergy" value="gluten"><span>Gluten</span></label>
|
|
<label><input type="checkbox" name="allergy" value="dairy"><span>Sut Urunleri</span></label>
|
|
<label><input type="checkbox" name="allergy" value="nuts"><span>Kuruyemis</span></label>
|
|
<label><input type="checkbox" name="allergy" value="eggs"><span>Yumurta</span></label>
|
|
<label><input type="checkbox" name="allergy" value="soy"><span>Soya</span></label>
|
|
<label><input type="checkbox" name="allergy" value="shellfish"><span>Kabuklu Deniz Urunleri</span></label>
|
|
<label><input type="checkbox" name="allergy" value="fish"><span>Balik</span></label>
|
|
<label><input type="checkbox" name="allergy" value="wheat"><span>Bugday</span></label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Diyet Kisitlamalari</label>
|
|
<div class="checkbox-group">
|
|
<label><input type="checkbox" name="dietRestriction" value="vegan"><span>Vegan</span></label>
|
|
<label><input type="checkbox" name="dietRestriction" value="vegetarian"><span>Vejetaryen</span></label>
|
|
<label><input type="checkbox" name="dietRestriction" value="gluten_free"><span>Glutensiz</span></label>
|
|
<label><input type="checkbox" name="dietRestriction" value="dairy_free"><span>Laktozsuz</span></label>
|
|
<label><input type="checkbox" name="dietRestriction" value="nut_free"><span>Kuruyemissiz</span></label>
|
|
<label><input type="checkbox" name="dietRestriction" value="halal"><span>Helal</span></label>
|
|
<label><input type="checkbox" name="dietRestriction" value="kosher"><span>Koser</span></label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Gida Intoleranslari</label>
|
|
<div class="checkbox-group">
|
|
<label><input type="checkbox" name="intolerance" value="lactose"><span>Laktoz</span></label>
|
|
<label><input type="checkbox" name="intolerance" value="fructose"><span>Fruktoz</span></label>
|
|
<label><input type="checkbox" name="intolerance" value="histamine"><span>Histamin</span></label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Mevcut Takviyeler</label>
|
|
<textarea id="profSupplements" placeholder="orn: Whey protein, kreatin, omega-3..."></textarea>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label>Kafein Tuketimi</label>
|
|
<select id="profCaffeine">
|
|
<option value="none">Yok</option>
|
|
<option value="low">Az</option>
|
|
<option value="moderate">Orta</option>
|
|
<option value="high">Cok</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Sigara</label>
|
|
<div class="radio-group">
|
|
<label>
|
|
<input type="radio" name="smoking" value="no" checked>
|
|
<span>Hayir</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="smoking" value="yes">
|
|
<span>Evet</span>
|
|
</label>
|
|
<label>
|
|
<input type="radio" name="smoking" value="quit">
|
|
<span>Biraktim</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Alkol</label>
|
|
<select id="profAlcohol">
|
|
<option value="none">Hic</option>
|
|
<option value="occasional">Ara Sira</option>
|
|
<option value="moderate">Orta</option>
|
|
<option value="heavy">Agir</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="step-buttons">
|
|
<button class="btn btn-secondary" onclick="profileNextStep(6)">Geri</button>
|
|
<button class="btn btn-primary btn-lg" onclick="saveProfile()" id="saveProfileBtn">Programimi Olustur</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- DASHBOARD -->
|
|
<div id="dashboardPage" class="hidden">
|
|
<div class="container">
|
|
<div class="dashboard-header">
|
|
<h1 id="dashGreeting">Merhaba!</h1>
|
|
<p>Kisisel fitness ve beslenme programiniz hazir.</p>
|
|
</div>
|
|
|
|
<div class="stats-grid" id="statsGrid"></div>
|
|
|
|
<div style="display:flex;justify-content:flex-end;margin-bottom:16px;gap:8px;flex-wrap:wrap;">
|
|
<button class="btn btn-outline btn-sm" onclick="showPage('profile')">Profili Duzenle</button>
|
|
<button class="btn btn-outline btn-sm" onclick="regeneratePrograms()">Programlari Yenile</button>
|
|
</div>
|
|
|
|
<div class="tabs">
|
|
<button class="tab-btn active" data-tab="workout" onclick="switchTab('workout')">Antrenman</button>
|
|
<button class="tab-btn" data-tab="meal" onclick="switchTab('meal')">Beslenme Plani</button>
|
|
<button class="tab-btn" data-tab="shopping" onclick="switchTab('shopping')">Alisveris</button>
|
|
<button class="tab-btn" data-tab="tips" onclick="switchTab('tips')">Oneriler</button>
|
|
</div>
|
|
|
|
<!-- Workout Tab -->
|
|
<div id="workoutTab"></div>
|
|
|
|
<!-- Meal Tab -->
|
|
<div id="mealTab" class="hidden"></div>
|
|
|
|
<!-- Shopping Tab -->
|
|
<div id="shoppingTab" class="hidden"></div>
|
|
|
|
<!-- Tips Tab -->
|
|
<div id="tipsTab" class="hidden"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// ======================== STATE ========================
|
|
var token = localStorage.getItem('token');
|
|
var currentUser = null;
|
|
var currentProfile = null;
|
|
var workoutData = null;
|
|
var mealData = null;
|
|
var shoppingData = null;
|
|
var tipsData = null;
|
|
var currentWeek = 1;
|
|
|
|
// ======================== API ========================
|
|
async function api(path, options) {
|
|
options = options || {};
|
|
var headers = { 'Content-Type': 'application/json' };
|
|
if (token) headers['Authorization'] = 'Bearer ' + token;
|
|
var res = await fetch(path, Object.assign({}, options, { headers: headers }));
|
|
var data = await res.json();
|
|
if (!res.ok) throw new Error(data.error || 'Bir hata olustu');
|
|
return data;
|
|
}
|
|
|
|
// ======================== AUTH ========================
|
|
async function handleLogin(e) {
|
|
e.preventDefault();
|
|
var btn = document.getElementById('loginBtn');
|
|
var errEl = document.getElementById('loginError');
|
|
errEl.style.display = 'none';
|
|
btn.disabled = true;
|
|
btn.textContent = 'Giris yapiliyor...';
|
|
try {
|
|
var data = await api('/api/auth/login', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
email: document.getElementById('loginEmail').value,
|
|
password: document.getElementById('loginPassword').value,
|
|
}),
|
|
});
|
|
token = data.token;
|
|
localStorage.setItem('token', token);
|
|
currentUser = data.user;
|
|
await checkProfileAndRoute();
|
|
} catch (err) {
|
|
errEl.textContent = err.message;
|
|
errEl.style.display = 'block';
|
|
} finally {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Giris Yap';
|
|
}
|
|
}
|
|
|
|
async function handleRegister(e) {
|
|
e.preventDefault();
|
|
var btn = document.getElementById('regBtn');
|
|
var errEl = document.getElementById('registerError');
|
|
errEl.style.display = 'none';
|
|
btn.disabled = true;
|
|
btn.textContent = 'Kayit olunuyor...';
|
|
try {
|
|
var data = await api('/api/auth/register', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
name: document.getElementById('regName').value,
|
|
email: document.getElementById('regEmail').value,
|
|
password: document.getElementById('regPassword').value,
|
|
}),
|
|
});
|
|
token = data.token;
|
|
localStorage.setItem('token', token);
|
|
currentUser = data.user;
|
|
showPage('profile');
|
|
} catch (err) {
|
|
errEl.textContent = err.message;
|
|
errEl.style.display = 'block';
|
|
} finally {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Kayit Ol';
|
|
}
|
|
}
|
|
|
|
function logout() {
|
|
token = null;
|
|
currentUser = null;
|
|
currentProfile = null;
|
|
workoutData = null;
|
|
mealData = null;
|
|
shoppingData = null;
|
|
tipsData = null;
|
|
currentWeek = 1;
|
|
localStorage.removeItem('token');
|
|
showPage('login');
|
|
}
|
|
|
|
// ======================== NAVIGATION ========================
|
|
function showPage(page) {
|
|
var pages = ['loginPage','registerPage','profilePage','dashboardPage'];
|
|
pages.forEach(function(p) { document.getElementById(p).classList.add('hidden'); });
|
|
document.getElementById('navUserInfo').style.display = 'none';
|
|
|
|
switch(page) {
|
|
case 'login':
|
|
document.getElementById('loginPage').classList.remove('hidden');
|
|
break;
|
|
case 'register':
|
|
document.getElementById('registerPage').classList.remove('hidden');
|
|
break;
|
|
case 'profile':
|
|
document.getElementById('profilePage').classList.remove('hidden');
|
|
document.getElementById('navUserInfo').style.display = 'flex';
|
|
if (currentProfile) populateProfileForm(currentProfile);
|
|
profileNextStep(1);
|
|
break;
|
|
case 'dashboard':
|
|
document.getElementById('dashboardPage').classList.remove('hidden');
|
|
document.getElementById('navUserInfo').style.display = 'flex';
|
|
break;
|
|
}
|
|
|
|
if (currentUser) {
|
|
document.getElementById('navUserName').textContent = currentUser.name;
|
|
}
|
|
}
|
|
|
|
async function checkProfileAndRoute() {
|
|
try {
|
|
if (!currentUser) {
|
|
var me = await api('/api/auth/me');
|
|
currentUser = me.user;
|
|
}
|
|
var profileRes = await api('/api/profile');
|
|
currentProfile = profileRes.profile;
|
|
if (currentProfile) {
|
|
showPage('dashboard');
|
|
loadDashboard();
|
|
} else {
|
|
showPage('profile');
|
|
}
|
|
} catch (err) {
|
|
logout();
|
|
}
|
|
}
|
|
|
|
// ======================== PROFILE ========================
|
|
var TOTAL_STEPS = 7;
|
|
var stepLabels = {
|
|
1: 'Adim 1/7 - Temel Bilgiler',
|
|
2: 'Adim 2/7 - Vucut Olculeri (Opsiyonel)',
|
|
3: 'Adim 3/7 - Yasam Tarzi',
|
|
4: 'Adim 4/7 - Antrenman Tercihleri',
|
|
5: 'Adim 5/7 - Sakatlik & Engellilik',
|
|
6: 'Adim 6/7 - Tibbi Gecmis',
|
|
7: 'Adim 7/7 - Beslenme Tercihleri',
|
|
};
|
|
|
|
function profileNextStep(step) {
|
|
for (var s = 1; s <= TOTAL_STEPS; s++) {
|
|
document.getElementById('profileStep' + s).classList.toggle('hidden', s !== step);
|
|
}
|
|
document.querySelectorAll('.step-dot').forEach(function(dot) {
|
|
var ds = parseInt(dot.dataset.step);
|
|
dot.classList.toggle('active', ds === step);
|
|
dot.classList.toggle('done', ds < step);
|
|
});
|
|
document.getElementById('progressBarFill').style.width = (step / TOTAL_STEPS * 100) + '%';
|
|
document.getElementById('stepLabel').textContent = stepLabels[step] || '';
|
|
document.getElementById('profileError').style.display = 'none';
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
}
|
|
|
|
// Toggle helpers
|
|
function toggleInjuryFields() {
|
|
var checked = document.getElementById('profHasInjury').checked;
|
|
document.getElementById('injuryFields').classList.toggle('hidden', !checked);
|
|
}
|
|
|
|
function toggleDisabilityFields() {
|
|
var checked = document.getElementById('profHasDisability').checked;
|
|
document.getElementById('disabilityFields').classList.toggle('hidden', !checked);
|
|
}
|
|
|
|
function toggleProstheticFields() {
|
|
var checked = document.getElementById('profHasProsthetic').checked;
|
|
document.getElementById('prostheticFields').classList.toggle('hidden', !checked);
|
|
}
|
|
|
|
function toggleEquipmentFields() {
|
|
var checked = document.getElementById('profHasEquipment').checked;
|
|
document.getElementById('equipmentFields').classList.toggle('hidden', !checked);
|
|
}
|
|
|
|
function toggleMedField(id) {
|
|
var el = document.getElementById(id);
|
|
var toggleMap = {
|
|
heartDetail: 'profHeartCondition',
|
|
diabetesDetail: 'profHasDiabetes',
|
|
thyroidDetail: 'profHasThyroid',
|
|
arthritisDetail: 'profHasArthritis'
|
|
};
|
|
var checkbox = document.getElementById(toggleMap[id]);
|
|
el.classList.toggle('hidden', !checkbox.checked);
|
|
}
|
|
|
|
// Workout location selector
|
|
function selectLocation(value) {
|
|
document.getElementById('profWorkoutLocation').value = value;
|
|
document.querySelectorAll('.location-card').forEach(function(card) {
|
|
card.classList.toggle('selected', card.dataset.value === value);
|
|
});
|
|
document.getElementById('gymFields').classList.toggle('hidden', value !== 'gym');
|
|
document.getElementById('homeFields').classList.toggle('hidden', value !== 'home');
|
|
document.getElementById('noneFields').classList.toggle('hidden', value !== 'none');
|
|
}
|
|
|
|
// Radio/checkbox helpers
|
|
function getRadioValue(name) {
|
|
var el = document.querySelector('input[name="' + name + '"]:checked');
|
|
return el ? el.value : '';
|
|
}
|
|
|
|
function setRadioValue(name, value) {
|
|
if (!value) return;
|
|
var el = document.querySelector('input[name="' + name + '"][value="' + value + '"]');
|
|
if (el) el.checked = true;
|
|
}
|
|
|
|
function getCheckedValues(name) {
|
|
var els = document.querySelectorAll('input[name="' + name + '"]:checked');
|
|
var values = [];
|
|
els.forEach(function(el) { values.push(el.value); });
|
|
return values;
|
|
}
|
|
|
|
function setCheckedValues(name, values) {
|
|
if (!values || !Array.isArray(values)) return;
|
|
values.forEach(function(v) {
|
|
var el = document.querySelector('input[name="' + name + '"][value="' + v + '"]');
|
|
if (el) el.checked = true;
|
|
});
|
|
}
|
|
|
|
function populateProfileForm(p) {
|
|
// Step 1
|
|
if (p.age) document.getElementById('profAge').value = p.age;
|
|
setRadioValue('profGender', p.gender);
|
|
if (p.height) document.getElementById('profHeight').value = p.height;
|
|
if (p.weight) document.getElementById('profWeight').value = p.weight;
|
|
if (p.target_weight) document.getElementById('profTargetWeight').value = p.target_weight;
|
|
|
|
// Step 2
|
|
if (p.body_fat_percentage) document.getElementById('profBodyFat').value = p.body_fat_percentage;
|
|
if (p.waist_circumference) document.getElementById('profWaist').value = p.waist_circumference;
|
|
if (p.hip_circumference) document.getElementById('profHip').value = p.hip_circumference;
|
|
if (p.neck_circumference) document.getElementById('profNeck').value = p.neck_circumference;
|
|
if (p.wrist_circumference) document.getElementById('profWrist').value = p.wrist_circumference;
|
|
if (p.chest_circumference) document.getElementById('profChest').value = p.chest_circumference;
|
|
if (p.arm_circumference) document.getElementById('profArm').value = p.arm_circumference;
|
|
if (p.thigh_circumference) document.getElementById('profThigh').value = p.thigh_circumference;
|
|
if (p.calf_circumference) document.getElementById('profCalf').value = p.calf_circumference;
|
|
setRadioValue('bodyType', p.body_type);
|
|
|
|
// Step 3
|
|
if (p.goal) {
|
|
var goals = typeof p.goal === 'string' ? p.goal.split(',').map(function(s){return s.trim();}) : [p.goal];
|
|
setCheckedValues('profGoal', goals);
|
|
}
|
|
if (p.activity_level) {
|
|
var activities = typeof p.activity_level === 'string' ? p.activity_level.split(',').map(function(s){return s.trim();}) : [p.activity_level];
|
|
setCheckedValues('profActivity', activities);
|
|
}
|
|
if (p.job_type) document.getElementById('profJobType').value = p.job_type;
|
|
if (p.sleep_hours) document.getElementById('profSleep').value = p.sleep_hours;
|
|
setRadioValue('sleepQuality', p.sleep_quality);
|
|
if (p.water_intake) document.getElementById('profWater').value = p.water_intake;
|
|
setRadioValue('stressLevel', p.stress_level);
|
|
if (p.daily_steps) document.getElementById('profDailySteps').value = p.daily_steps;
|
|
|
|
// Step 4 - Workout
|
|
if (p.workout_location) {
|
|
selectLocation(p.workout_location);
|
|
if (p.workout_location === 'gym') {
|
|
if (p.workout_experience) document.getElementById('profExperience').value = p.workout_experience;
|
|
if (p.workout_days_per_week) document.getElementById('profWorkoutDays').value = p.workout_days_per_week;
|
|
if (p.workout_duration_minutes) document.getElementById('profWorkoutDuration').value = p.workout_duration_minutes;
|
|
if (p.fitness_goal) {
|
|
var fgoals = typeof p.fitness_goal === 'string' ? p.fitness_goal.split(',').map(function(s){return s.trim();}) : [p.fitness_goal];
|
|
setCheckedValues('profFitnessGoal', fgoals);
|
|
}
|
|
if (p.cardio_preference) {
|
|
var cprefs = typeof p.cardio_preference === 'string' ? p.cardio_preference.split(',').map(function(s){return s.trim();}) : [p.cardio_preference];
|
|
setCheckedValues('profCardioPreference', cprefs);
|
|
}
|
|
} else if (p.workout_location === 'home') {
|
|
if (p.workout_experience) document.getElementById('profExperienceHome').value = p.workout_experience;
|
|
if (p.workout_days_per_week) document.getElementById('profWorkoutDaysHome').value = p.workout_days_per_week;
|
|
if (p.workout_duration_minutes) document.getElementById('profWorkoutDurationHome').value = p.workout_duration_minutes;
|
|
if (p.has_equipment) {
|
|
document.getElementById('profHasEquipment').checked = true;
|
|
toggleEquipmentFields();
|
|
if (p.available_equipment) {
|
|
var equip = typeof p.available_equipment === 'string' ? p.available_equipment.split(',').map(function(s){return s.trim();}) : p.available_equipment;
|
|
setCheckedValues('equipment', equip);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 5 - Injury & Disability
|
|
if (p.has_injury) {
|
|
document.getElementById('profHasInjury').checked = true;
|
|
toggleInjuryFields();
|
|
if (p.injury_area) {
|
|
var areas = typeof p.injury_area === 'string' ? p.injury_area.split(',').map(function(s){return s.trim();}) : [p.injury_area];
|
|
setCheckedValues('profInjuryArea', areas);
|
|
}
|
|
setRadioValue('injurySeverity', p.injury_severity);
|
|
if (p.injury_notes) document.getElementById('profInjuryNotes').value = p.injury_notes;
|
|
}
|
|
if (p.has_disability) {
|
|
document.getElementById('profHasDisability').checked = true;
|
|
toggleDisabilityFields();
|
|
setRadioValue('disabilityType', p.disability_type);
|
|
if (p.disability_details) document.getElementById('profDisabilityDetails').value = p.disability_details;
|
|
setRadioValue('mobilityLevel', p.mobility_level);
|
|
if (p.uses_wheelchair) document.getElementById('profUsesWheelchair').checked = true;
|
|
if (p.has_prosthetic) {
|
|
document.getElementById('profHasProsthetic').checked = true;
|
|
toggleProstheticFields();
|
|
if (p.prosthetic_area) document.getElementById('profProstheticArea').value = p.prosthetic_area;
|
|
}
|
|
}
|
|
|
|
// Step 6 - Medical
|
|
if (p.heart_condition) {
|
|
document.getElementById('profHeartCondition').checked = true;
|
|
toggleMedField('heartDetail');
|
|
if (p.heart_condition_details) document.getElementById('profHeartConditionDetails').value = p.heart_condition_details;
|
|
}
|
|
if (p.has_diabetes) {
|
|
document.getElementById('profHasDiabetes').checked = true;
|
|
toggleMedField('diabetesDetail');
|
|
setRadioValue('diabetesType', p.diabetes_type);
|
|
}
|
|
if (p.has_thyroid) {
|
|
document.getElementById('profHasThyroid').checked = true;
|
|
toggleMedField('thyroidDetail');
|
|
setRadioValue('thyroidType', p.thyroid_type);
|
|
}
|
|
if (p.has_asthma) document.getElementById('profHasAsthma').checked = true;
|
|
if (p.has_epilepsy) document.getElementById('profHasEpilepsy').checked = true;
|
|
if (p.has_arthritis) {
|
|
document.getElementById('profHasArthritis').checked = true;
|
|
toggleMedField('arthritisDetail');
|
|
setRadioValue('arthritisType', p.arthritis_type);
|
|
}
|
|
if (p.has_osteoporosis) document.getElementById('profHasOsteoporosis').checked = true;
|
|
if (p.has_fibromyalgia) document.getElementById('profHasFibromyalgia').checked = true;
|
|
if (p.blood_type) document.getElementById('profBloodType').value = p.blood_type;
|
|
if (p.blood_pressure) document.getElementById('profBloodPressure').value = p.blood_pressure;
|
|
if (p.blood_sugar) document.getElementById('profBloodSugar').value = p.blood_sugar;
|
|
if (p.cholesterol_level) document.getElementById('profCholesterol').value = p.cholesterol_level;
|
|
if (p.mental_health) document.getElementById('profMentalHealth').value = p.mental_health;
|
|
if (p.health_conditions) document.getElementById('profHealthConditions').value = p.health_conditions;
|
|
if (p.chronic_diseases) document.getElementById('profChronicDiseases').value = p.chronic_diseases;
|
|
if (p.medications) document.getElementById('profMedications').value = p.medications;
|
|
if (p.surgeries) document.getElementById('profSurgeries').value = p.surgeries;
|
|
|
|
// Step 7 - Nutrition
|
|
if (p.meals_per_day) {
|
|
document.getElementById('profMeals').value = p.meals_per_day;
|
|
document.getElementById('mealsValue').textContent = p.meals_per_day;
|
|
}
|
|
if (p.allergies) {
|
|
var allergies = typeof p.allergies === 'string' ? p.allergies.split(',').map(function(s){return s.trim();}) : p.allergies;
|
|
setCheckedValues('allergy', allergies);
|
|
}
|
|
if (p.dietary_restrictions) {
|
|
var diets = typeof p.dietary_restrictions === 'string' ? p.dietary_restrictions.split(',').map(function(s){return s.trim();}) : p.dietary_restrictions;
|
|
setCheckedValues('dietRestriction', diets);
|
|
}
|
|
if (p.food_intolerances) {
|
|
var intol = typeof p.food_intolerances === 'string' ? p.food_intolerances.split(',').map(function(s){return s.trim();}) : p.food_intolerances;
|
|
setCheckedValues('intolerance', intol);
|
|
}
|
|
if (p.supplement_use) document.getElementById('profSupplements').value = p.supplement_use;
|
|
if (p.caffeine_intake) document.getElementById('profCaffeine').value = p.caffeine_intake;
|
|
setRadioValue('smoking', p.smoking);
|
|
if (p.alcohol) document.getElementById('profAlcohol').value = p.alcohol;
|
|
}
|
|
|
|
async function saveProfile() {
|
|
var btn = document.getElementById('saveProfileBtn');
|
|
var errEl = document.getElementById('profileError');
|
|
errEl.style.display = 'none';
|
|
btn.disabled = true;
|
|
btn.textContent = 'Kaydediliyor...';
|
|
try {
|
|
var wl = document.getElementById('profWorkoutLocation').value || 'gym';
|
|
var workoutExp = '';
|
|
var workoutDaysVal = null;
|
|
var workoutDurVal = null;
|
|
|
|
if (wl === 'gym') {
|
|
workoutExp = document.getElementById('profExperience').value;
|
|
workoutDaysVal = parseInt(document.getElementById('profWorkoutDays').value) || null;
|
|
workoutDurVal = parseInt(document.getElementById('profWorkoutDuration').value) || null;
|
|
} else if (wl === 'home') {
|
|
workoutExp = document.getElementById('profExperienceHome').value;
|
|
workoutDaysVal = parseInt(document.getElementById('profWorkoutDaysHome').value) || null;
|
|
workoutDurVal = parseInt(document.getElementById('profWorkoutDurationHome').value) || null;
|
|
}
|
|
|
|
var body = {
|
|
// Step 1
|
|
age: parseInt(document.getElementById('profAge').value),
|
|
gender: getRadioValue('profGender'),
|
|
height: parseFloat(document.getElementById('profHeight').value),
|
|
weight: parseFloat(document.getElementById('profWeight').value),
|
|
target_weight: parseFloat(document.getElementById('profTargetWeight').value) || null,
|
|
|
|
// Step 2
|
|
body_fat_percentage: parseFloat(document.getElementById('profBodyFat').value) || null,
|
|
waist_circumference: parseFloat(document.getElementById('profWaist').value) || null,
|
|
hip_circumference: parseFloat(document.getElementById('profHip').value) || null,
|
|
neck_circumference: parseFloat(document.getElementById('profNeck').value) || null,
|
|
wrist_circumference: parseFloat(document.getElementById('profWrist').value) || null,
|
|
chest_circumference: parseFloat(document.getElementById('profChest').value) || null,
|
|
arm_circumference: parseFloat(document.getElementById('profArm').value) || null,
|
|
thigh_circumference: parseFloat(document.getElementById('profThigh').value) || null,
|
|
calf_circumference: parseFloat(document.getElementById('profCalf').value) || null,
|
|
body_type: getRadioValue('bodyType') || null,
|
|
|
|
// Step 3
|
|
goal: getCheckedValues('profGoal').join(','),
|
|
activity_level: getCheckedValues('profActivity').join(','),
|
|
job_type: document.getElementById('profJobType').value || null,
|
|
sleep_hours: parseFloat(document.getElementById('profSleep').value) || null,
|
|
sleep_quality: getRadioValue('sleepQuality') || null,
|
|
water_intake: parseFloat(document.getElementById('profWater').value) || null,
|
|
stress_level: getRadioValue('stressLevel') || null,
|
|
daily_steps: parseInt(document.getElementById('profDailySteps').value) || null,
|
|
|
|
// Step 4
|
|
workout_location: wl,
|
|
workout_experience: workoutExp || null,
|
|
workout_days_per_week: workoutDaysVal,
|
|
workout_duration_minutes: workoutDurVal,
|
|
fitness_goal: (wl === 'gym' ? getCheckedValues('profFitnessGoal').join(',') : null) || null,
|
|
cardio_preference: (wl === 'gym' ? getCheckedValues('profCardioPreference').join(',') : null) || null,
|
|
has_equipment: (wl === 'home' ? (document.getElementById('profHasEquipment').checked ? 1 : 0) : null),
|
|
available_equipment: (wl === 'home' ? getCheckedValues('equipment').join(',') : null) || null,
|
|
|
|
// Step 5
|
|
has_injury: document.getElementById('profHasInjury').checked ? 1 : 0,
|
|
injury_area: getCheckedValues('profInjuryArea').join(',') || 'none',
|
|
injury_severity: getRadioValue('injurySeverity') || null,
|
|
injury_notes: document.getElementById('profInjuryNotes').value || null,
|
|
has_disability: document.getElementById('profHasDisability').checked ? 1 : 0,
|
|
disability_type: getRadioValue('disabilityType') || 'none',
|
|
disability_details: document.getElementById('profDisabilityDetails').value || null,
|
|
mobility_level: getRadioValue('mobilityLevel') || 'full',
|
|
uses_wheelchair: document.getElementById('profUsesWheelchair').checked ? 1 : 0,
|
|
has_prosthetic: document.getElementById('profHasProsthetic').checked ? 1 : 0,
|
|
prosthetic_area: document.getElementById('profProstheticArea').value || null,
|
|
|
|
// Step 6
|
|
heart_condition: document.getElementById('profHeartCondition').checked ? 1 : 0,
|
|
heart_condition_details: document.getElementById('profHeartConditionDetails').value || null,
|
|
has_diabetes: document.getElementById('profHasDiabetes').checked ? 1 : 0,
|
|
diabetes_type: getRadioValue('diabetesType') || null,
|
|
has_thyroid: document.getElementById('profHasThyroid').checked ? 1 : 0,
|
|
thyroid_type: getRadioValue('thyroidType') || null,
|
|
has_asthma: document.getElementById('profHasAsthma').checked ? 1 : 0,
|
|
has_epilepsy: document.getElementById('profHasEpilepsy').checked ? 1 : 0,
|
|
has_arthritis: document.getElementById('profHasArthritis').checked ? 1 : 0,
|
|
arthritis_type: getRadioValue('arthritisType') || null,
|
|
has_osteoporosis: document.getElementById('profHasOsteoporosis').checked ? 1 : 0,
|
|
has_fibromyalgia: document.getElementById('profHasFibromyalgia').checked ? 1 : 0,
|
|
blood_type: document.getElementById('profBloodType').value || null,
|
|
blood_pressure: document.getElementById('profBloodPressure').value || null,
|
|
blood_sugar: document.getElementById('profBloodSugar').value || null,
|
|
cholesterol_level: document.getElementById('profCholesterol').value || null,
|
|
mental_health: document.getElementById('profMentalHealth').value || 'none',
|
|
health_conditions: document.getElementById('profHealthConditions').value || null,
|
|
chronic_diseases: document.getElementById('profChronicDiseases').value || null,
|
|
medications: document.getElementById('profMedications').value || null,
|
|
surgeries: document.getElementById('profSurgeries').value || null,
|
|
|
|
// Step 7
|
|
meals_per_day: parseInt(document.getElementById('profMeals').value) || 5,
|
|
allergies: getCheckedValues('allergy').join(',') || '',
|
|
dietary_restrictions: getCheckedValues('dietRestriction').join(',') || '',
|
|
food_intolerances: getCheckedValues('intolerance').join(',') || '',
|
|
supplement_use: document.getElementById('profSupplements').value || null,
|
|
caffeine_intake: document.getElementById('profCaffeine').value || 'none',
|
|
smoking: getRadioValue('smoking') || 'no',
|
|
alcohol: document.getElementById('profAlcohol').value || 'none',
|
|
};
|
|
|
|
if (!body.age || !body.gender || !body.height || !body.weight || !body.goal || !body.activity_level) {
|
|
throw new Error('Lutfen tum zorunlu alanlari doldurun (yas, cinsiyet, boy, kilo, hedef, aktivite)');
|
|
}
|
|
|
|
var res = await api('/api/profile', { method: 'POST', body: JSON.stringify(body) });
|
|
currentProfile = res.profile;
|
|
workoutData = null;
|
|
mealData = null;
|
|
shoppingData = null;
|
|
tipsData = null;
|
|
currentWeek = 1;
|
|
showPage('dashboard');
|
|
loadDashboard();
|
|
} catch (err) {
|
|
errEl.textContent = err.message;
|
|
errEl.style.display = 'block';
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
} finally {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Programimi Olustur';
|
|
}
|
|
}
|
|
|
|
// ======================== DASHBOARD ========================
|
|
async function loadDashboard() {
|
|
if (!currentProfile) return;
|
|
document.getElementById('dashGreeting').textContent = 'Merhaba, ' + (currentUser ? currentUser.name : '') + '!';
|
|
renderStats();
|
|
await loadWorkout();
|
|
}
|
|
|
|
function calculateBMI(weight, height) {
|
|
if (!weight || !height) return null;
|
|
var h = height / 100;
|
|
return Math.round((weight / (h * h)) * 10) / 10;
|
|
}
|
|
|
|
function getBMICategory(bmi) {
|
|
if (bmi < 18.5) return { text: 'Zayif', cls: 'badge-blue' };
|
|
if (bmi < 25) return { text: 'Normal', cls: 'badge-green' };
|
|
if (bmi < 30) return { text: 'Kilolu', cls: 'badge-orange' };
|
|
return { text: 'Obez', cls: 'badge-red' };
|
|
}
|
|
|
|
function renderStats() {
|
|
var p = currentProfile;
|
|
var goalNames = { lose_weight:'Kilo Verme', gain_weight:'Kilo Alma', build_muscle:'Kas Gelistirme', maintain:'Form Koruma' };
|
|
var locationNames = { gym:'Spor Salonu', home:'Ev', none:'Egzersiz Yok' };
|
|
var locationIcons = { gym:'🏋️', home:'🏠', none:'❌' };
|
|
|
|
var bmi = calculateBMI(p.weight, p.height);
|
|
var bmiCat = bmi ? getBMICategory(bmi) : null;
|
|
|
|
var targetSub = p.target_weight ? ('Hedef: ' + p.target_weight + ' kg') : '';
|
|
var bmiHtml = bmi ? (bmi + ' <span class="badge ' + bmiCat.cls + '">' + bmiCat.text + '</span>') : '-';
|
|
|
|
var html = '';
|
|
html += '<div class="stat-card"><div class="stat-value">' + bmiHtml + '</div><div class="stat-label">BMI</div>';
|
|
html += '<div class="stat-sub">' + p.height + ' cm / ' + p.weight + ' kg</div></div>';
|
|
|
|
html += '<div class="stat-card"><div class="stat-value">' + (goalNames[p.goal] || p.goal) + '</div><div class="stat-label">Hedef</div>';
|
|
if (targetSub) html += '<div class="stat-sub">' + targetSub + '</div>';
|
|
html += '</div>';
|
|
|
|
// Workout location badge
|
|
var wl = p.workout_location || 'gym';
|
|
html += '<div class="stat-card"><div class="stat-value" style="font-size:1.2rem;">' + (locationIcons[wl] || '') + ' ' + (locationNames[wl] || wl) + '</div><div class="stat-label">Antrenman Yeri</div></div>';
|
|
|
|
// Daily calories placeholder (will be filled from meal data)
|
|
html += '<div class="stat-card" id="calorieStatCard"><div class="stat-value">-</div><div class="stat-label">Gunluk Kalori</div></div>';
|
|
|
|
if (p.has_injury) {
|
|
var injAreas = { knee:'Diz', back:'Sirt', shoulder:'Omuz', elbow:'Dirsek', wrist:'Bilek', ankle:'Ayak Bilegi', hip:'Kalca', neck:'Boyun' };
|
|
html += '<div class="stat-card" style="border-left:4px solid var(--orange);"><div class="stat-value" style="color:var(--orange);font-size:1.2rem;">' + (injAreas[p.injury_area] || '-') + '</div><div class="stat-label">Sakatlik</div></div>';
|
|
}
|
|
|
|
if (p.has_disability) {
|
|
html += '<div class="stat-card" style="border-left:4px solid var(--blue);"><div class="stat-value" style="color:var(--blue);font-size:1rem;">Engellilik</div><div class="stat-label">' + (p.disability_type || '') + '</div></div>';
|
|
}
|
|
|
|
document.getElementById('statsGrid').innerHTML = html;
|
|
}
|
|
|
|
function switchTab(tab) {
|
|
document.querySelectorAll('.tab-btn').forEach(function(b) { b.classList.toggle('active', b.dataset.tab === tab); });
|
|
['workoutTab','mealTab','shoppingTab','tipsTab'].forEach(function(t) { document.getElementById(t).classList.add('hidden'); });
|
|
document.getElementById(tab + 'Tab').classList.remove('hidden');
|
|
|
|
if (tab === 'workout' && !workoutData) loadWorkout();
|
|
if (tab === 'meal' && !mealData) loadMeal();
|
|
if (tab === 'shopping' && !shoppingData) loadShopping();
|
|
if (tab === 'tips' && !tipsData) loadTips();
|
|
}
|
|
|
|
async function regeneratePrograms() {
|
|
workoutData = null;
|
|
mealData = null;
|
|
shoppingData = null;
|
|
tipsData = null;
|
|
var activeTab = document.querySelector('.tab-btn.active').dataset.tab;
|
|
if (activeTab === 'workout') await loadWorkout();
|
|
else if (activeTab === 'meal') await loadMeal();
|
|
else if (activeTab === 'shopping') await loadShopping();
|
|
else await loadTips();
|
|
}
|
|
|
|
// ======================== WORKOUT ========================
|
|
async function loadWorkout() {
|
|
var el = document.getElementById('workoutTab');
|
|
el.innerHTML = '<div class="loading"><div class="spinner"></div>Antrenman programi hazirlaniyor...</div>';
|
|
try {
|
|
workoutData = await api('/api/program/workout?week=' + currentWeek);
|
|
renderWorkout(el);
|
|
} catch (err) {
|
|
el.innerHTML = '<div class="content-card"><p class="error-msg">' + err.message + '</p></div>';
|
|
}
|
|
}
|
|
|
|
function selectWeek(week) {
|
|
currentWeek = week;
|
|
workoutData = null;
|
|
loadWorkout();
|
|
}
|
|
|
|
function renderWorkout(el) {
|
|
var d = workoutData;
|
|
var phaseNames = { Foundation:'Temel', Progression:'Ilerleme', Overreach:'Yuklenme', Deload:'Deload' };
|
|
var phaseClasses = { Foundation:'badge-green', Progression:'badge-blue', Overreach:'badge-orange', Deload:'badge-purple' };
|
|
var typeNames = { strength:'Kuvvet', cardio:'Kardiyo', rest:'Dinlenme', flexibility:'Esneklik', active_recovery:'Aktif Toparlanma', light_activity:'Hafif Aktivite' };
|
|
|
|
// Week selector
|
|
var html = '<div class="week-selector">';
|
|
html += '<span class="label">Hafta:</span>';
|
|
for (var w = 1; w <= 4; w++) {
|
|
var wLabel = 'Hafta ' + w;
|
|
if (w === 1) wLabel += ' (Temel)';
|
|
else if (w === 2) wLabel += ' (Ilerleme)';
|
|
else if (w === 3) wLabel += ' (Yuklenme)';
|
|
else if (w === 4) wLabel += ' (Deload)';
|
|
html += '<button class="week-btn' + (w === currentWeek ? ' active' : '') + '" onclick="selectWeek(' + w + ')">' + wLabel + '</button>';
|
|
}
|
|
html += '</div>';
|
|
|
|
// Phase badge and title
|
|
var phase = d.mesocycle_phase || 'Foundation';
|
|
html += '<div class="content-card">';
|
|
html += '<h3>' + d.title + ' <span class="badge ' + (phaseClasses[phase] || 'badge-green') + '">' + (phaseNames[phase] || phase) + '</span></h3>';
|
|
html += '<p style="color:var(--gray);margin-bottom:8px;">Hafta ' + d.week + ' / 4</p>';
|
|
|
|
// Injury/disability notes
|
|
if (d.injury_note) {
|
|
html += '<div class="warning-box">' + d.injury_note + '</div>';
|
|
}
|
|
if (d.disability_note) {
|
|
html += '<div class="warning-box" style="border-left-color:var(--blue);background:#eaf2f8;color:#2c3e50;">' + d.disability_note + '</div>';
|
|
}
|
|
if (d.medical_notes) {
|
|
html += '<div class="warning-box" style="border-left-color:var(--purple);background:#f4ecf7;color:#6c3483;">' + d.medical_notes + '</div>';
|
|
}
|
|
|
|
if (d.general_tips && d.general_tips.length > 0) {
|
|
html += '<ul class="tips-list">' + d.general_tips.map(function(t) { return '<li>' + t + '</li>'; }).join('') + '</ul>';
|
|
}
|
|
html += '</div>';
|
|
|
|
// Days
|
|
if (d.days && d.days.length > 0) {
|
|
d.days.forEach(function(day, i) {
|
|
var badgeClass = 'badge-' + (day.type || 'rest');
|
|
|
|
html += '<div class="day-card">';
|
|
html += '<div class="day-header" onclick="toggleDayBody(this)">';
|
|
html += '<h3>' + day.day + ' - ' + (day.title || '') + '</h3>';
|
|
html += '<div class="day-meta">';
|
|
if (day.estimated_duration) html += '<span class="day-duration">' + day.estimated_duration + ' dk</span>';
|
|
if (day.estimated_calories) html += '<span class="day-duration">' + day.estimated_calories + ' kcal</span>';
|
|
html += '<span class="badge ' + badgeClass + '">' + (typeNames[day.type] || day.type || '') + '</span>';
|
|
html += '</div>';
|
|
html += '</div>';
|
|
html += '<div class="day-body' + (i === 0 ? ' open' : '') + '">';
|
|
|
|
// Warmup
|
|
if (day.warmup || d.warmup_routine) {
|
|
var warmup = day.warmup || d.warmup_routine;
|
|
if (warmup && warmup.length > 0) {
|
|
html += '<div class="routine-section">';
|
|
html += '<h4>Isinma Rutini</h4>';
|
|
warmup.forEach(function(w) {
|
|
html += '<div class="routine-item">';
|
|
html += '<span class="routine-name">' + w.name + '</span>';
|
|
html += '<span class="routine-dur">' + (w.duration || '') + '</span>';
|
|
html += '</div>';
|
|
if (w.notes) html += '<div style="font-size:0.75rem;color:var(--gray);margin-bottom:4px;padding-left:4px;">' + w.notes + '</div>';
|
|
});
|
|
html += '</div>';
|
|
}
|
|
}
|
|
|
|
// Exercises with GIF
|
|
if (day.exercises && day.exercises.length > 0) {
|
|
day.exercises.forEach(function(ex) {
|
|
html += '<div class="exercise-card">';
|
|
|
|
// GIF
|
|
if (ex.gif) {
|
|
html += '<div class="exercise-gif">';
|
|
html += '<img src="' + ex.gif + '" alt="' + (ex.name || '') + '" loading="lazy" onerror="this.style.display=\'none\'; this.nextElementSibling.style.display=\'flex\'">';
|
|
html += '<div class="gif-placeholder" style="display:none"><span class="gif-icon">🏋️</span><span>GIF bulunamadi</span></div>';
|
|
html += '</div>';
|
|
} else {
|
|
html += '<div class="exercise-gif">';
|
|
html += '<div class="gif-placeholder"><span class="gif-icon">🏋️</span><span>' + (ex.name || '') + '</span></div>';
|
|
html += '</div>';
|
|
}
|
|
|
|
html += '<div class="exercise-details">';
|
|
html += '<div class="ex-name">' + (ex.name || '') + '</div>';
|
|
|
|
// Meta tags
|
|
html += '<div class="ex-meta">';
|
|
if (ex.sets) html += '<span class="ex-tag">' + ex.sets + ' Set</span>';
|
|
if (ex.reps) html += '<span class="ex-tag">' + ex.reps + ' Tekrar</span>';
|
|
if (ex.rest_seconds > 0) html += '<span class="ex-tag">' + ex.rest_seconds + 'sn Dinlenme</span>';
|
|
if (ex.tempo) html += '<span class="ex-tag">Tempo: ' + ex.tempo + '</span>';
|
|
html += '</div>';
|
|
|
|
// Muscle & equipment badges
|
|
html += '<div class="ex-meta">';
|
|
if (ex.muscle_group) html += '<span class="ex-muscle">' + ex.muscle_group + '</span>';
|
|
if (ex.equipment) html += '<span class="ex-equipment">' + ex.equipment + '</span>';
|
|
html += '</div>';
|
|
|
|
// Instructions
|
|
if (ex.instructions && ex.instructions.length > 0) {
|
|
html += '<ol class="ex-instructions">';
|
|
ex.instructions.forEach(function(inst) {
|
|
html += '<li>' + inst + '</li>';
|
|
});
|
|
html += '</ol>';
|
|
}
|
|
|
|
if (ex.notes) html += '<div class="ex-notes">' + ex.notes + '</div>';
|
|
|
|
// Alternatives
|
|
if (ex.alternatives && ex.alternatives.length > 0) {
|
|
html += '<div class="ex-alternatives">Alternatifler: ' + ex.alternatives.join(', ') + '</div>';
|
|
}
|
|
|
|
html += '</div>'; // exercise-details
|
|
html += '</div>'; // exercise-card
|
|
});
|
|
}
|
|
|
|
// Cooldown
|
|
if (day.cooldown && day.cooldown.length > 0) {
|
|
html += '<div class="routine-section" style="margin-top:14px;">';
|
|
html += '<h4>Soguma Rutini</h4>';
|
|
day.cooldown.forEach(function(c) {
|
|
html += '<div class="routine-item">';
|
|
html += '<span class="routine-name">' + c.name + '</span>';
|
|
html += '<span class="routine-dur">' + (c.duration || '') + '</span>';
|
|
html += '</div>';
|
|
if (c.notes) html += '<div style="font-size:0.75rem;color:var(--gray);margin-bottom:4px;padding-left:4px;">' + c.notes + '</div>';
|
|
});
|
|
html += '</div>';
|
|
}
|
|
|
|
// Rest day / light activity message
|
|
if (day.type === 'rest' || day.type === 'active_recovery' || day.type === 'light_activity') {
|
|
if (day.description) {
|
|
html += '<div class="info-box" style="margin-top:8px;">' + day.description + '</div>';
|
|
}
|
|
}
|
|
|
|
html += '</div></div>';
|
|
});
|
|
}
|
|
|
|
el.innerHTML = html;
|
|
}
|
|
|
|
function toggleDayBody(header) {
|
|
var body = header.nextElementSibling;
|
|
body.classList.toggle('open');
|
|
}
|
|
|
|
// ======================== MEAL PLAN ========================
|
|
async function loadMeal() {
|
|
var el = document.getElementById('mealTab');
|
|
el.innerHTML = '<div class="loading"><div class="spinner"></div>Beslenme plani hazirlaniyor...</div>';
|
|
try {
|
|
mealData = await api('/api/program/meal');
|
|
renderMeal(el);
|
|
// Update calorie stat card
|
|
if (mealData.daily_calories) {
|
|
var calCard = document.getElementById('calorieStatCard');
|
|
if (calCard) {
|
|
calCard.innerHTML = '<div class="stat-value">' + mealData.daily_calories + '</div><div class="stat-label">Gunluk Kalori (kcal)</div>';
|
|
if (mealData.macros) {
|
|
calCard.innerHTML += '<div class="stat-sub">P:' + mealData.macros.protein_g + 'g K:' + mealData.macros.carbs_g + 'g Y:' + mealData.macros.fat_g + 'g</div>';
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
el.innerHTML = '<div class="content-card"><p class="error-msg">' + err.message + '</p></div>';
|
|
}
|
|
}
|
|
|
|
function renderMeal(el) {
|
|
var d = mealData;
|
|
var html = '';
|
|
|
|
// Diet type badge
|
|
if (d.diet_type) {
|
|
html += '<div style="margin-bottom:16px;"><span class="badge badge-green" style="font-size:0.85rem;padding:4px 14px;">' + d.diet_type + '</span></div>';
|
|
}
|
|
|
|
// Medical adjustments
|
|
if (d.medical_adjustments) {
|
|
html += '<div class="warning-box" style="border-left-color:var(--purple);background:#f4ecf7;color:#6c3483;">' + d.medical_adjustments + '</div>';
|
|
}
|
|
|
|
// Body metrics card
|
|
if (d.body_metrics) {
|
|
var bm = d.body_metrics;
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Vucut Metrikleri</h3>';
|
|
html += '<div class="metrics-card">';
|
|
if (bm.bmi) html += '<div class="metric-item"><div class="metric-value">' + bm.bmi + '</div><div class="metric-label">BMI</div></div>';
|
|
if (bm.ideal_weight_min && bm.ideal_weight_max) html += '<div class="metric-item"><div class="metric-value">' + bm.ideal_weight_min + '-' + bm.ideal_weight_max + '</div><div class="metric-label">Ideal Kilo (kg)</div></div>';
|
|
if (bm.waist_to_hip_ratio) html += '<div class="metric-item"><div class="metric-value">' + bm.waist_to_hip_ratio + '</div><div class="metric-label">Bel/Kalca Orani <span class="badge ' + (bm.whr_risk === 'Normal' ? 'badge-green' : 'badge-red') + '">' + bm.whr_risk + '</span></div></div>';
|
|
if (bm.bmi_category) html += '<div class="metric-item"><div class="metric-value">' + bm.bmi_category + '</div><div class="metric-label">BMI Kategorisi</div></div>';
|
|
html += '</div></div>';
|
|
}
|
|
|
|
// Daily targets
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Gunluk Kalori & Makro Hedefleri</h3>';
|
|
html += '<div class="stats-grid" style="margin:0 0 16px 0;">';
|
|
html += '<div class="stat-card"><div class="stat-value">' + (d.daily_calories || '-') + '</div><div class="stat-label">Gunluk Kalori (kcal)</div></div>';
|
|
if (d.macros) {
|
|
html += '<div class="stat-card"><div class="stat-value">' + d.macros.protein_g + 'g</div><div class="stat-label">Protein</div></div>';
|
|
html += '<div class="stat-card"><div class="stat-value">' + d.macros.carbs_g + 'g</div><div class="stat-label">Karbonhidrat</div></div>';
|
|
html += '<div class="stat-card"><div class="stat-value">' + d.macros.fat_g + 'g</div><div class="stat-label">Yag</div></div>';
|
|
}
|
|
html += '</div>';
|
|
|
|
if (d.recommended_water_liters) {
|
|
html += '<p style="margin-bottom:12px;"><strong>Gunluk Su Onerisi:</strong> ' + d.recommended_water_liters + ' litre</p>';
|
|
}
|
|
html += '<div style="text-align:right;"><button class="btn btn-outline btn-sm" onclick="window.print()">Yazdir</button></div>';
|
|
html += '</div>';
|
|
|
|
// Supplements
|
|
if (d.supplements && d.supplements.length > 0) {
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Takviye Onerileri</h3>';
|
|
d.supplements.forEach(function(s) {
|
|
html += '<div class="supplement-item">';
|
|
html += '<div><div class="supplement-name">' + s.name + '</div>';
|
|
if (s.reason) html += '<div class="supplement-reason">' + s.reason + '</div>';
|
|
html += '</div>';
|
|
html += '<div class="supplement-dosage">' + (s.dosage || '') + '</div>';
|
|
html += '</div>';
|
|
});
|
|
html += '</div>';
|
|
}
|
|
|
|
// Notes
|
|
if (d.notes && d.notes.length > 0) {
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Beslenme Notlari</h3>';
|
|
html += '<ul class="tips-list">' + d.notes.map(function(n) { return '<li>' + n + '</li>'; }).join('') + '</ul>';
|
|
html += '</div>';
|
|
}
|
|
|
|
// Meals
|
|
if (d.meals && d.meals.length > 0) {
|
|
var totalCals = 0;
|
|
d.meals.forEach(function(m) { totalCals += (m.calories || 0); });
|
|
|
|
html += '<div class="meal-day-card">';
|
|
html += '<div class="meal-day-header" onclick="toggleDayBody(this)">';
|
|
html += '<h3>Gunluk Beslenme Plani</h3>';
|
|
html += '<span>' + totalCals + ' kcal</span>';
|
|
html += '</div>';
|
|
html += '<div class="meal-day-body open">';
|
|
d.meals.forEach(function(m) {
|
|
html += '<div class="meal-item">';
|
|
html += '<div class="meal-type">' + (m.type || '') + '</div>';
|
|
html += '<div class="meal-name">' + (m.name || '') + '</div>';
|
|
html += '<div class="meal-macros">';
|
|
html += '<span class="macro-tag macro-cal">' + (m.calories || 0) + ' kcal</span>';
|
|
html += '<span class="macro-tag macro-pro">P: ' + (m.protein || 0) + 'g</span>';
|
|
html += '<span class="macro-tag macro-carb">K: ' + (m.carbs || 0) + 'g</span>';
|
|
html += '<span class="macro-tag macro-fat">Y: ' + (m.fat || 0) + 'g</span>';
|
|
if (m.fiber) html += '<span class="macro-tag macro-fiber">L: ' + m.fiber + 'g</span>';
|
|
html += '</div>';
|
|
if (m.ingredients && m.ingredients.length > 0) {
|
|
html += '<div class="meal-ingredients">';
|
|
m.ingredients.forEach(function(ing) {
|
|
var ingName = typeof ing === 'string' ? ing : (ing.item + ' (' + ing.grams + 'g)');
|
|
html += '<span>' + ingName + '</span>';
|
|
});
|
|
html += '</div>';
|
|
}
|
|
html += '</div>';
|
|
});
|
|
html += '</div></div>';
|
|
}
|
|
|
|
el.innerHTML = html;
|
|
}
|
|
|
|
// ======================== SHOPPING LIST ========================
|
|
async function loadShopping() {
|
|
var el = document.getElementById('shoppingTab');
|
|
el.innerHTML = '<div class="loading"><div class="spinner"></div>Alisveris listesi hazirlaniyor...</div>';
|
|
try {
|
|
shoppingData = await api('/api/program/shopping');
|
|
renderShopping(el);
|
|
} catch (err) {
|
|
el.innerHTML = '<div class="content-card"><p class="error-msg">' + err.message + '</p></div>';
|
|
}
|
|
}
|
|
|
|
function renderShopping(el) {
|
|
var d = shoppingData;
|
|
var html = '';
|
|
|
|
html += '<div class="content-card">';
|
|
html += '<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">';
|
|
html += '<div>';
|
|
html += '<h3>' + (d.title || 'Alisveris Listesi') + '</h3>';
|
|
html += '<p style="color:var(--gray);font-size:0.9rem;">' + (d.note || '') + ' (' + (d.total_items || 0) + ' urun)</p>';
|
|
html += '</div>';
|
|
html += '<button class="btn btn-outline btn-sm" onclick="window.print()">Yazdir</button>';
|
|
html += '</div></div>';
|
|
|
|
if (d.categories) {
|
|
for (var key in d.categories) {
|
|
if (!d.categories.hasOwnProperty(key)) continue;
|
|
var cat = d.categories[key];
|
|
html += '<div class="content-card shopping-category">';
|
|
html += '<h4>' + (cat.icon || '') + ' ' + (cat.name || key) + ' (' + (cat.items ? cat.items.length : 0) + ')</h4>';
|
|
if (cat.items) {
|
|
cat.items.forEach(function(item) {
|
|
html += '<div class="shopping-item">';
|
|
html += '<span class="item-name">' + item.item + '</span>';
|
|
html += '<span class="item-amount">' + (item.display_amount || item.total_grams + 'g') + '</span>';
|
|
html += '</div>';
|
|
});
|
|
}
|
|
html += '</div>';
|
|
}
|
|
}
|
|
|
|
el.innerHTML = html;
|
|
}
|
|
|
|
// ======================== TIPS ========================
|
|
async function loadTips() {
|
|
var el = document.getElementById('tipsTab');
|
|
el.innerHTML = '<div class="loading"><div class="spinner"></div>Oneriler yukleniyor...</div>';
|
|
try {
|
|
// Tips are gathered from workout and meal data
|
|
if (!workoutData) {
|
|
try { workoutData = await api('/api/program/workout?week=' + currentWeek); } catch(e) {}
|
|
}
|
|
if (!mealData) {
|
|
try { mealData = await api('/api/program/meal'); } catch(e) {}
|
|
}
|
|
tipsData = true;
|
|
renderTips(el);
|
|
} catch (err) {
|
|
el.innerHTML = '<div class="content-card"><p class="error-msg">' + err.message + '</p></div>';
|
|
}
|
|
}
|
|
|
|
function renderTips(el) {
|
|
var html = '';
|
|
|
|
// Medical notes
|
|
var medNotes = [];
|
|
if (workoutData && workoutData.medical_notes) medNotes.push(workoutData.medical_notes);
|
|
if (workoutData && workoutData.injury_note) medNotes.push(workoutData.injury_note);
|
|
if (workoutData && workoutData.disability_note) medNotes.push(workoutData.disability_note);
|
|
if (mealData && mealData.medical_adjustments) medNotes.push(mealData.medical_adjustments);
|
|
|
|
if (medNotes.length > 0) {
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Saglik Notlari</h3>';
|
|
medNotes.forEach(function(note) {
|
|
html += '<div class="warning-box" style="margin-bottom:8px;">' + note + '</div>';
|
|
});
|
|
html += '</div>';
|
|
}
|
|
|
|
// Supplements
|
|
if (mealData && mealData.supplements && mealData.supplements.length > 0) {
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Takviye Onerileri</h3>';
|
|
mealData.supplements.forEach(function(s) {
|
|
html += '<div class="supplement-item">';
|
|
html += '<div><div class="supplement-name">' + s.name + '</div>';
|
|
if (s.reason) html += '<div class="supplement-reason">' + s.reason + '</div>';
|
|
html += '</div>';
|
|
html += '<div class="supplement-dosage">' + (s.dosage || '') + '</div>';
|
|
html += '</div>';
|
|
});
|
|
html += '</div>';
|
|
}
|
|
|
|
// General tips from workout
|
|
if (workoutData && workoutData.general_tips && workoutData.general_tips.length > 0) {
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Antrenman Onerileri</h3>';
|
|
html += '<ul class="tips-list">' + workoutData.general_tips.map(function(t) { return '<li>' + t + '</li>'; }).join('') + '</ul>';
|
|
html += '</div>';
|
|
}
|
|
|
|
// Nutrition notes
|
|
if (mealData && mealData.notes && mealData.notes.length > 0) {
|
|
html += '<div class="content-card">';
|
|
html += '<h3>Beslenme Onerileri</h3>';
|
|
html += '<ul class="tips-list">' + mealData.notes.map(function(n) { return '<li>' + n + '</li>'; }).join('') + '</ul>';
|
|
html += '</div>';
|
|
}
|
|
|
|
if (!html) {
|
|
html = '<div class="content-card"><p style="color:var(--gray);text-align:center;">Henuz oneri bulunmuyor. Once antrenman ve beslenme planlarinizi olusturun.</p></div>';
|
|
}
|
|
|
|
el.innerHTML = html;
|
|
}
|
|
|
|
// ======================== INIT ========================
|
|
(async function init() {
|
|
if (token) {
|
|
await checkProfileAndRoute();
|
|
} else {
|
|
showPage('login');
|
|
}
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|