ba-cafe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

NewFeatureDialog.tsx (4379B)


      1 "use client";
      2 
      3 import { useState, useEffect } from 'react';
      4 import { UPDATE_LOGS } from '@/lib/updateLogs';
      5 
      6 export default function NewFeatureDialog() {
      7   const [isOpen, setIsOpen] = useState(false);
      8   const [isChecked, setIsChecked] = useState(false);
      9 
     10   const latestLog = UPDATE_LOGS[0];
     11   const pastLogs = UPDATE_LOGS.slice(1);
     12   
     13   const latestLogId = latestLog ? `${latestLog.date}_${latestLog.content}` : 'initial';
     14 
     15   useEffect(() => {
     16     if (typeof window !== 'undefined') {
     17       const lastNotifiedId = localStorage.getItem('new_feature_notified_id');
     18       if (lastNotifiedId !== latestLogId) {
     19         setIsOpen(true);
     20       }
     21     }
     22   }, [latestLogId]);
     23 
     24   const handleClose = () => {
     25     if (isChecked) {
     26       localStorage.setItem('new_feature_notified_id', latestLogId);
     27     }
     28     setIsOpen(false);
     29   };
     30 
     31   if (!isOpen) return null;
     32 
     33   return (
     34     <div className="fixed inset-0 bg-black/40 dark:bg-black/60 z-100 flex justify-center items-center p-4 animate-in fade-in duration-200 backdrop-blur-sm">
     35       <div className="w-full max-w-sm rounded-2xl shadow-xl border border-dashed bg-(--card) border-(--muted) flex flex-col overflow-hidden animate-in zoom-in-95 duration-200">
     36         
     37         <div className="border-b border-dashed flex justify-between items-center p-5">
     38           <h2 className="text-xl font-bold text-(--foreground) tracking-wide flex items-center gap-2">
     39             アップデートのお知らせ
     40           </h2>
     41         </div>
     42 
     43         <div className=" flex flex-col text-sm font-medium leading-relaxed text-(--secondary-foreground)">
     44           
     45           {/* 1. 最新の更新履歴とコメント(上部に大きく配置) */}
     46           {latestLog && (
     47             <div className="bg-(--background) p-4 border border-dashed border-(--primary)/30 flex flex-col gap-2">
     48               <div className="flex items-center gap-2 text-s font-bold text-(--secondary-foreground)">
     49                 <span>{latestLog.date}</span>
     50               </div>
     51               <strong className="text-base font-bold text-(--foreground) block">
     52                 {latestLog.content}
     53               </strong>
     54               {latestLog.comment && (
     55                 <p className="text-sm text-(--secondary-foreground) font-medium">
     56                   {latestLog.comment}
     57                 </p>
     58               )}
     59             </div>
     60           )}
     61           
     62           {/* 2. それ以前の更新履歴(下部にリスト表示) */}
     63           {pastLogs.length > 0 && (
     64             <div className="flex flex-col gap-2">
     65               <div className="show-scrollbar bg-(--background) p-4 border border-dashed border-(--muted)/60 flex flex-col gap-2.5 max-h-36 overflow-y-auto">
     66                 {pastLogs.map((log, index) => (
     67                   <div key={index} className="flex flex-col gap-0.5 text-xs">
     68                     <div className="flex gap-3">
     69                       <span className="shrink-0 font-bold text-(--muted-foreground)">{log.date}</span>
     70                       <p className="text-(--secondary-foreground)">{log.content}</p>
     71                     </div>
     72                     {log.comment && (
     73                       <p className="text-[11px] text-(--secondary-foreground)/70 pl-18.5 leading-normal">
     74                         {log.comment}
     75                       </p>
     76                     )}
     77                   </div>
     78                 ))}
     79               </div>
     80             </div>
     81           )}
     82         </div>
     83 
     84         <div className="p-4 bg-(--background)/50 border-t border-dashed border-(--muted)/40 flex flex-col gap-3">
     85           <label className="flex items-center gap-2 px-1 cursor-pointer select-none text-xs text-(--secondary-foreground) font-bold">
     86             <input 
     87               type="checkbox"
     88               checked={isChecked}
     89               onChange={(e) => setIsChecked(e.target.checked)}
     90               className="w-4 h-4 rounded border-(--muted) text-(--primary) focus:ring-(--primary) cursor-pointer"
     91             />
     92             <span>今回のアップデートノートを今後表示しない</span>
     93           </label>
     94 
     95           <button
     96             onClick={handleClose}
     97             className="w-full py-3 rounded-xl font-bold bg-(--primary) text-(--primary-foreground) transition-all active:scale-98 cursor-pointer shadow-sm hover:brightness-105"
     98           >
     99             OK
    100           </button>
    101         </div>
    102 
    103       </div>
    104     </div>
    105   );
    106 }