@@ -2882,7 +2882,41 @@ async function analyzeResponseWithLLM(question, answer, profile) {
28822882}
28832883
28842884export const offlineApi = {
2885- // ... (keep getMe, login, register, getProfile, updateProfile)
2885+ getMe ( token ) {
2886+ if ( ! token || ! token . startsWith ( 'offline:' ) ) return { success : false } ;
2887+ const userId = Number ( token . replace ( 'offline:' , '' ) ) ;
2888+ const user = getUsers ( ) . find ( ( u ) => u . id === userId ) ;
2889+ if ( ! user ) return { success : false } ;
2890+ return { success : true , data : { user_id : user . id , email : user . email , user_type : user . user_type } } ;
2891+ } ,
2892+ login ( { email, password } ) {
2893+ const user = getUsers ( ) . find ( ( u ) => u . email === email && u . password === password ) ;
2894+ if ( ! user ) return { success : false , error : 'Sai email hoặc mật khẩu' } ;
2895+ const token = `offline:${ user . id } ` ;
2896+ return { success : true , data : { user_id : user . id , email : user . email , user_type : user . user_type , token } } ;
2897+ } ,
2898+ register ( { email, password, user_type } ) {
2899+ const users = getUsers ( ) ;
2900+ if ( users . find ( ( u ) => u . email === email ) ) {
2901+ return { success : false , error : 'Email đã tồn tại' } ;
2902+ }
2903+ const nextId = Math . max ( 1 , ...users . map ( ( u ) => u . id ) ) + 1 ;
2904+ const user = { id : nextId , email, password, user_type : user_type || 'high_school' } ;
2905+ users . push ( user ) ;
2906+ saveUsers ( users ) ;
2907+ const token = `offline:${ user . id } ` ;
2908+ return { success : true , data : { user_id : user . id , email : user . email , user_type : user . user_type , token } } ;
2909+ } ,
2910+ getProfile ( userId ) {
2911+ const profiles = getProfiles ( ) ;
2912+ return { success : true , data : profiles [ userId ] || null } ;
2913+ } ,
2914+ updateProfile ( userId , payload ) {
2915+ const profiles = getProfiles ( ) ;
2916+ profiles [ userId ] = { ...profiles [ userId ] , ...payload } ;
2917+ saveProfiles ( profiles ) ;
2918+ return { success : true , data : { updated : true } } ;
2919+ } ,
28862920 async sendMessage ( { conversation_id, message, user_id, request_more, profile } ) {
28872921 const convId = conversation_id || `conv_${ Date . now ( ) } _${ Math . floor ( Math . random ( ) * 1000 ) } ` ;
28882922 ensureConversation ( convId , user_id || null , message ) ;
@@ -2929,7 +2963,7 @@ export const offlineApi = {
29292963 Object . keys ( derived ) . forEach ( ( tag ) => addTagScore ( state . tags , tag , derived [ tag ] ) ) ;
29302964 }
29312965
2932- // Update focus tags if detected (legacy but useful)
2966+ // Update focus tags if detected
29332967 const subjectTag = detectSubjectTag ( message ) ;
29342968 const groupTag = detectGroupTag ( message ) ;
29352969 if ( subjectTag ) {
@@ -2993,36 +3027,40 @@ export const offlineApi = {
29933027 return { success : true , data : getRecommendations ( conversationId ) } ;
29943028 } ,
29953029 renameConversation ( conversationId , title ) {
2996- updateConversationTitle ( conversationId , title ) ;
2997- return { success : true , data : { updated : true } } ;
3030+ const convs = getConversations ( ) ;
3031+ const idx = convs . findIndex ( ( c ) => c . conversation_id === conversationId ) ;
3032+ if ( idx !== - 1 ) {
3033+ convs [ idx ] . title = title ;
3034+ saveConversations ( convs ) ;
3035+ }
3036+ return { success : true } ;
29983037 } ,
29993038 deleteConversation ( conversationId ) {
3000- removeConversation ( conversationId ) ;
3001- return { success : true , data : { deleted : true } } ;
3039+ const convs = getConversations ( ) . filter ( ( c ) => c . conversation_id !== conversationId ) ;
3040+ saveConversations ( convs ) ;
3041+ localStorage . removeItem ( `messages:${ conversationId } ` ) ;
3042+ localStorage . removeItem ( `recommendations:${ conversationId } ` ) ;
3043+ localStorage . removeItem ( `state:${ conversationId } ` ) ;
3044+ return { success : true } ;
30023045 } ,
30033046 deleteHistory ( userId ) {
3004- clearHistoryForUser ( userId ) ;
3005- return { success : true , data : { deleted : true } } ;
3047+ const convs = getConversations ( ) . filter ( ( c ) => c . user_id !== userId ) ;
3048+ saveConversations ( convs ) ;
3049+ return { success : true } ;
30063050 } ,
30073051 exploreFilters ( ) {
3008- const categories = Array . from ( new Set ( CAREERS . map ( ( c ) => c . category ) ) ) . filter ( Boolean ) ;
3009- const tags = Array . from ( new Set ( CAREERS . flatMap ( ( c ) => c . tags ) ) ) . filter ( Boolean ) ;
3010- return { success : true , data : { categories, tags } } ;
3052+ return {
3053+ success : true ,
3054+ data : {
3055+ categories : Array . from ( new Set ( BASE_CAREERS . map ( ( c ) => c . category ) ) ) ,
3056+ tags : Array . from ( new Set ( BASE_CAREERS . flatMap ( ( c ) => c . tags ) ) )
3057+ }
3058+ } ;
30113059 } ,
30123060 exploreJobs ( { q, category, tag, limit = 120 , offset = 0 } ) {
3013- console . log ( '[OfflineStore] exploreJobs called' , { q, category, tag, limit, offset, careersCount : CAREERS . length } ) ;
3014-
3015- // Fix image path for GitHub Pages
3016- const getBasePath = ( ) => {
3017- const path = window . location . pathname ;
3018- return path . includes ( '/myAIchatbotProject' ) ? '/myAIchatbotProject' : '' ;
3019- } ;
3020- const basePath = getBasePath ( ) ;
3021-
30223061 // Map category to icon
3023- const getIcon = ( cat ) => {
3062+ const getMappingIcon = ( cat ) => {
30243063 const key = normalizeText ( cat || '' ) . toLowerCase ( ) . trim ( ) ;
3025-
30263064 const MAPPING = {
30273065 'agriculture' : 'agri.svg' ,
30283066 'beauty' : 'service.svg' ,
@@ -3056,22 +3094,23 @@ export const offlineApi = {
30563094 'community' : 'community.svg' ,
30573095 'admin' : 'admin.svg'
30583096 } ;
3059-
30603097 return MAPPING [ key ] || 'default.svg' ;
30613098 } ;
30623099
30633100 const query = normalizeText ( String ( q || '' ) ) ;
3064-
3065- // Simplified path per user request to avoid duplication
30663101 const imgPrefix = 'career-icons/' ;
30673102
3068- let list = CAREERS . map ( ( c , idx ) => ( {
3103+ let list = BASE_CAREERS . map ( ( c , idx ) => ( {
30693104 id : idx + 1 ,
3105+ career_name : c . name ,
30703106 title : c . name ,
30713107 category : c . category ,
30723108 tags : c . tags ,
3073- image_url : `${ imgPrefix } ${ getIcon ( c . category ) } `
3109+ description : `Mô tả cho ${ c . name } ...` ,
3110+ salary : '10M - 50M VNĐ' ,
3111+ image_url : `${ imgPrefix } ${ getMappingIcon ( c . category ) } `
30743112 } ) ) ;
3113+
30753114 if ( query ) {
30763115 list = list . filter ( ( j ) => {
30773116 const title = normalizeText ( j . title ) ;
@@ -3084,6 +3123,7 @@ export const offlineApi = {
30843123 if ( tag ) {
30853124 list = list . filter ( ( j ) => j . tags . includes ( tag ) ) ;
30863125 }
3126+
30873127 const total = list . length ;
30883128 const slice = list . slice ( offset , offset + limit ) ;
30893129 return { success : true , data : slice , total } ;
0 commit comments