You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

page.tsx 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. 'use client';
  2. import React, { useEffect, useState } from 'react';
  3. import PageTitle from '@/components/ui/PageTitle';
  4. import {
  5. EyeOutlined,
  6. EditOutlined,
  7. SortAscendingOutlined,
  8. PlusCircleFilled
  9. } from '@ant-design/icons';
  10. import type { Persona } from '@/types/persona';
  11. import { getPersona } from '@/app/api/user/personaService';
  12. import { useQuery } from '@tanstack/react-query';
  13. import PrimaryButton from '@/components/ui/PrimaryButton';
  14. import { Flex, Row, Col, Tag, Button, Table, Layout, Image, Typography } from 'antd';
  15. import type { ColumnsType } from 'antd/es/table';
  16. import { useRouter } from 'next/navigation';
  17. import LoadingScreen from '@/components/layout/LoadingScreen';
  18. const { Text, Title } = Typography;
  19. const columns: ColumnsType<Persona> = [
  20. {
  21. title: (
  22. <Text className="flex items-center gap-1">
  23. Name <SortAscendingOutlined className="text-xs text-gray-400" />
  24. </Text>
  25. ),
  26. dataIndex: 'name',
  27. key: 'name',
  28. },
  29. {
  30. title: (
  31. <Text className="flex items-center gap-1">
  32. Role <SortAscendingOutlined className="text-xs text-gray-400" />
  33. </Text>
  34. ),
  35. dataIndex: 'role',
  36. key: 'role',
  37. },
  38. {
  39. title: (
  40. <Text className="flex items-center gap-1">
  41. Status <SortAscendingOutlined className="text-xs text-gray-400" />
  42. </Text>
  43. ),
  44. dataIndex: 'active',
  45. key: 'status',
  46. align: 'center' as const,
  47. render: (active: boolean) => (
  48. <Tag color={active ? 'green' : 'orange'} className="!rounded-full">
  49. {active ? 'Active' : 'Inactive'}
  50. </Tag>
  51. ),
  52. },
  53. {
  54. title: 'Action',
  55. key: 'action',
  56. align: 'center' as const,
  57. render: (_: any, record: Persona) => (
  58. <Flex justify="center">
  59. <Button type="text" icon={<EditOutlined />} />
  60. <Button type="text" icon={<EyeOutlined />} />
  61. </Flex>
  62. ),
  63. },
  64. ];
  65. const PersonaPage: React.FC = () => {
  66. const { data: personas, error, isLoading } = useQuery<Persona[]>({
  67. queryKey: ["getPersona"],
  68. queryFn: () => getPersona()
  69. })
  70. // Show loading state while fetching data
  71. if (isLoading) return <LoadingScreen />
  72. if (!personas) {
  73. return <p></p>
  74. }
  75. return (
  76. <Flex vertical className="!bg-white !h-full">
  77. <PageTitle>PERSONA</PageTitle>
  78. {(personas.length > 0) ? <PersonaList personaData={personas} /> : <PersonaIntro />}
  79. </Flex>
  80. );
  81. };
  82. const PersonaIntro: React.FC = () => {
  83. const router = useRouter();
  84. return (
  85. <Flex vertical flex={1} justify="center" align="center">
  86. <Row justify="center" style={{ width: '100%', padding: '0 24px' }}>
  87. <Col xs={24} sm={20} md={16} lg={12} xl={8}>
  88. <Flex
  89. vertical
  90. align="center"
  91. className="!text-center"
  92. style={{
  93. border: '2px solid #06b6d4', // cyan-500
  94. borderRadius: '12px',
  95. padding: '40px 24px',
  96. boxShadow: '0 10px 100px 30px rgba(59, 130, 246, 0.3)',
  97. background: 'white',
  98. }}
  99. >
  100. <Title level={5} style={{ marginBottom: 8, color: '#1f2937' }}>NO PERSONA CREATED YET</Title>
  101. <Text type="secondary" style={{ marginBottom: 24 }}>
  102. Get started by creating your first AI Persona
  103. </Text>
  104. <Image
  105. src="/Ruccan_Logo2.png"
  106. alt="Ruccan Logo"
  107. width={150}
  108. preview={false}
  109. style={{ marginBottom: 24 }}
  110. />
  111. <PrimaryButton onClick={() => router.push('/user/persona/create')}>
  112. CREATE YOUR FIRST PERSONA
  113. </PrimaryButton>
  114. </Flex>
  115. </Col>
  116. </Row>
  117. </Flex>
  118. )
  119. }
  120. interface PersonaListProps {
  121. personaData: Persona[] | undefined;
  122. }
  123. const PersonaList: React.FC<PersonaListProps> = ({ personaData }) => {
  124. const router = useRouter();
  125. return (
  126. <Layout className="!overflow-x-auto">
  127. <Flex className='!px-2 !py-4 !justify-end'>
  128. <PrimaryButton onClick={() => { router.push('persona/create') }}>
  129. <PlusCircleFilled /> Create New Persona
  130. </PrimaryButton>
  131. </Flex>
  132. <Table
  133. className="[&_.ant-table-cell]:!p-2"
  134. rowKey="id"
  135. columns={columns}
  136. dataSource={personaData}
  137. pagination={false}
  138. bordered
  139. />
  140. </Layout>
  141. );
  142. };
  143. export default PersonaPage;