// Main App: top bar, view router, drawer mounting.
const APPIcons = window.Icons;
const SESSION_KEY = 'akis_pm_session_v1';
const API_BASE = './api';
async function apiRequest(path, options = {}) {
const res = await fetch(`${API_BASE}${path}`, {
credentials: 'include',
headers: {
'Content-Type': 'application/json',
...(options.headers || {}),
},
...options,
});
const text = await res.text();
const data = text ? JSON.parse(text) : {};
if (!res.ok || data.ok === false) {
const err = new Error(data.error || `API error ${res.status}`);
err.status = res.status;
throw err;
}
return data;
}
function App() {
const store = window.PMStore.useStore();
const { state } = store;
const [session, setSession] = React.useState(() => {
try {
const raw = localStorage.getItem(SESSION_KEY);
return raw ? JSON.parse(raw) : null;
} catch (e) {
return null;
}
});
const [query, setQuery] = React.useState('');
const [selectedTaskId, setSelectedTaskId] = React.useState(null);
const [syncStatus, setSyncStatus] = React.useState('local');
const [remoteReady, setRemoteReady] = React.useState(false);
const [sidebarCollapsed, setSidebarCollapsed] = React.useState(() => {
try {
return localStorage.getItem('akis_sidebar_collapsed') === '1';
} catch (e) {
return false;
}
});
const loadRemoteState = async () => {
const data = await apiRequest('/state.php');
if (data.state) {
store.replaceState(data.state);
setRemoteReady(true);
setSyncStatus('online');
}
};
const login = async (user) => {
const cleanEmail = user.email;
const publicUser = {
email: cleanEmail,
name: user.name,
remember: user.remember,
signedInAt: user.signedInAt,
};
let nextUser = publicUser;
try {
const data = await apiRequest('/auth.php?action=login', {
method: 'POST',
body: JSON.stringify({ email: cleanEmail, password: user.password }),
});
nextUser = data.user || user;
localStorage.setItem(SESSION_KEY, JSON.stringify(nextUser));
setSession(nextUser);
await loadRemoteState();
} catch (e) {
if (e.status === 401 || e.status === 422) {
localStorage.removeItem(SESSION_KEY);
throw e;
}
nextUser = { ...publicUser, offline: true };
localStorage.setItem(SESSION_KEY, JSON.stringify(nextUser));
setSession(nextUser);
setRemoteReady(false);
setSyncStatus('local');
}
};
const logout = async () => {
try { await apiRequest('/auth.php?action=logout', { method: 'POST', body: '{}' }); } catch (e) {}
localStorage.removeItem(SESSION_KEY);
setSelectedTaskId(null);
setRemoteReady(false);
setSyncStatus('local');
setSession(null);
};
const clearLocalSession = () => {
localStorage.removeItem(SESSION_KEY);
setRemoteReady(false);
setSyncStatus('local');
setSession(null);
};
const refreshCloudSession = async () => {
try {
const me = await apiRequest('/auth.php?action=me');
if (me.user) {
localStorage.setItem(SESSION_KEY, JSON.stringify(me.user));
setSession(me.user);
}
await loadRemoteState();
} catch (e) {
setRemoteReady(false);
setSyncStatus('local');
if (e.status === 401) clearLocalSession();
}
};
const toggleSidebar = () => {
setSidebarCollapsed(v => {
const next = !v;
try { localStorage.setItem('akis_sidebar_collapsed', next ? '1' : '0'); } catch (e) {}
return next;
});
};
const selectedTask = selectedTaskId ? state.tasks.find(t => t.id === selectedTaskId) : null;
const openTask = (id) => setSelectedTaskId(id);
const closeTask = () => setSelectedTaskId(null);
const quickAddTask = (data = {}) => {
store.addTask({
title: 'Yeni görev',
status: data.status || 'todo',
priority: 'medium',
projectId: data.projectId || state.activeProjectId,
...data,
});
};
// Open newest task after add
const prevTaskCount = React.useRef(state.tasks.length);
React.useEffect(() => {
if (state.tasks.length > prevTaskCount.current) {
const newest = [...state.tasks]
.filter(t => t.createdAt)
.sort((a,b) => new Date(b.createdAt) - new Date(a.createdAt))[0];
if (newest) setSelectedTaskId(newest.id);
}
prevTaskCount.current = state.tasks.length;
}, [state.tasks.length]);
React.useEffect(() => {
if (!session) return;
refreshCloudSession();
}, [session?.email]);
React.useEffect(() => {
if (!session || !remoteReady) return;
const timer = setTimeout(() => {
apiRequest('/state.php', {
method: 'PUT',
body: JSON.stringify({ state }),
})
.then(() => setSyncStatus('online'))
.catch(() => setSyncStatus('offline'));
}, 700);
return () => clearTimeout(timer);
}, [state, session?.email, remoteReady]);
if (!session) {
return
Projeler, görevler ve takvim tek düzenli akışta.