big ui refractor
This commit is contained in:
@@ -97,7 +97,11 @@ export const processLesson = async (user, subjectId) => {
|
||||
if (!item) throw new Error('Item not found');
|
||||
|
||||
item.srsLevel = 1;
|
||||
item.nextReview = new Date();
|
||||
|
||||
const nextReview = new Date();
|
||||
nextReview.setUTCHours(nextReview.getUTCHours() + 2);
|
||||
nextReview.setUTCMinutes(0, 0, 0);
|
||||
item.nextReview = nextReview;
|
||||
|
||||
await item.save();
|
||||
return { success: true, item };
|
||||
|
||||
@@ -7,7 +7,6 @@ export const syncWithWaniKani = async (user) => {
|
||||
|
||||
console.log(`Starting sync for user: ${user._id}`);
|
||||
|
||||
// 1. Fetch all assigned Kanji Subject IDs
|
||||
let allSubjectIds = [];
|
||||
let nextUrl = 'https://api.wanikani.com/v2/assignments?subject_types=kanji&started=true';
|
||||
|
||||
@@ -26,26 +25,22 @@ export const syncWithWaniKani = async (user) => {
|
||||
|
||||
if (allSubjectIds.length === 0) return { count: 0, message: "No unlocked kanji found." };
|
||||
|
||||
// 2. Filter out items we already have
|
||||
const existingItems = await StudyItem.find({ userId: user._id }).select('wkSubjectId');
|
||||
const existingIds = new Set(existingItems.map(i => i.wkSubjectId));
|
||||
const newIds = allSubjectIds.filter(id => !existingIds.has(id));
|
||||
|
||||
console.log(`Found ${newIds.length} new items.`);
|
||||
|
||||
// 3. Process in chunks
|
||||
const CHUNK_SIZE = 50; // Reduced chunk size to accommodate secondary radical fetches
|
||||
const CHUNK_SIZE = 50;
|
||||
for (let i = 0; i < newIds.length; i += CHUNK_SIZE) {
|
||||
const chunk = newIds.slice(i, i + CHUNK_SIZE);
|
||||
|
||||
// A. Fetch Kanji Details
|
||||
const subRes = await fetch(`https://api.wanikani.com/v2/subjects?ids=${chunk.join(',')}`, {
|
||||
headers: { Authorization: `Bearer ${apiKey}` }
|
||||
});
|
||||
const subJson = await subRes.json();
|
||||
const kanjiDataList = subJson.data;
|
||||
|
||||
// B. Identify all needed Radicals
|
||||
const radicalIdsToFetch = new Set();
|
||||
kanjiDataList.forEach(k => {
|
||||
if (k.data.component_subject_ids) {
|
||||
@@ -53,11 +48,9 @@ export const syncWithWaniKani = async (user) => {
|
||||
}
|
||||
});
|
||||
|
||||
// C. Fetch Radical Details (if any)
|
||||
const radicalMap = new Map();
|
||||
if (radicalIdsToFetch.size > 0) {
|
||||
const rIds = Array.from(radicalIdsToFetch);
|
||||
// Fetch radicals in sub-chunks if necessary (max 100 per req)
|
||||
for (let j = 0; j < rIds.length; j += 100) {
|
||||
const rChunk = rIds.slice(j, j + 100);
|
||||
const rRes = await fetch(`https://api.wanikani.com/v2/subjects?ids=${rChunk.join(',')}`, {
|
||||
@@ -68,7 +61,6 @@ export const syncWithWaniKani = async (user) => {
|
||||
rJson.data.forEach(r => {
|
||||
const primaryMeaning = r.data.meanings.find(m => m.primary)?.meaning || 'Unknown';
|
||||
const char = r.data.characters;
|
||||
// Find SVG image if no character exists
|
||||
const image = !char && r.data.character_images
|
||||
? r.data.character_images.find(img => img.content_type === 'image/svg+xml' && !img.metadata.inline_styles)?.url
|
||||
: null;
|
||||
@@ -82,14 +74,12 @@ export const syncWithWaniKani = async (user) => {
|
||||
}
|
||||
}
|
||||
|
||||
// D. Build Database Objects
|
||||
const operations = kanjiDataList.map(d => {
|
||||
const readings = d.data.readings || [];
|
||||
|
||||
// Map the IDs to our fetched radical data
|
||||
const itemRadicals = (d.data.component_subject_ids || [])
|
||||
.map(rid => radicalMap.get(rid))
|
||||
.filter(Boolean); // Remove any not found
|
||||
.filter(Boolean);
|
||||
|
||||
return {
|
||||
userId: user._id,
|
||||
@@ -97,12 +87,12 @@ export const syncWithWaniKani = async (user) => {
|
||||
char: d.data.characters,
|
||||
meaning: d.data.meanings.find(m => m.primary)?.meaning || 'Unknown',
|
||||
level: d.data.level,
|
||||
srsLevel: 1,
|
||||
srsLevel: 0,
|
||||
nextReview: Date.now(),
|
||||
onyomi: readings.filter(r => r.type === 'onyomi').map(r => r.reading),
|
||||
kunyomi: readings.filter(r => r.type === 'kunyomi').map(r => r.reading),
|
||||
nanori: readings.filter(r => r.type === 'nanori').map(r => r.reading),
|
||||
radicals: itemRadicals, // Save them
|
||||
radicals: itemRadicals,
|
||||
stats: { correct: 0, total: 0 }
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user