INSTITUTO TECNOLÓGICO “DON BOSCO”
ÁREA: COMERCIAL Y SERVICIOS
CARRERA: SISTEMAS INFORMÁTICOS
“Sistema CRUD para Gestión de Proyectos de Grado”
POSTULANTE: Jireh Fernando Llanos Capcha
Materia: Diseño y Programación WEB III
EL ALTO – BOLIVIA
2025
1. Informe Técnico
2. Sistema CRUD para Gestión de Proyectos de Grado
3. 1. Breve descripción de la API
Se desarrolló una API RESTful en PHP que interactúa con una base de datos MySQL, la cual permite
realizar operaciones de gestión de proyectos de grado, como crear, consultar, actualizar y eliminar
registros. Esta API es consumida desde una aplicación móvil desarrollada con Flutter, que permite a
los usuarios interactuar de forma intuitiva con los datos.
4. 2. Código fuente de la API (PHP + MySQL)
5. [Link]
<?php
$host = "localhost";
$user = "root";
$pass = "";
$db = "proyectos_db"; // Nombre de la base de datos
$con = mysqli_connect($host, $user, $pass, $db);
if (!$con) {
die("Conexión fallida: " . mysqli_connect_error());
?>
6. get_projects.php
<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
include '[Link]';
$sql = "SELECT * FROM proyectos ORDER BY id DESC";
$result = mysqli_query($con, $sql);
$data = [];
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
echo json_encode($data);
?>
7. create_project.php
<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
include '[Link]';
$titulo = $_POST['titulo'];
$autor = $_POST['autor'];
$tutor = $_POST['tutor'];
$estado = $_POST['estado'];
$fecha = $_POST['fecha_presentacion'];
$sql = "INSERT INTO proyectos (titulo, autor, tutor, estado, fecha_presentacion)
VALUES ('$titulo', '$autor', '$tutor', '$estado', '$fecha')";
echo json_encode(['success' => mysqli_query($con, $sql)]);
?>
8. update_project.php
<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
include '[Link]';
$id = $_POST['id'];
$titulo = $_POST['titulo'];
$autor = $_POST['autor'];
$tutor = $_POST['tutor'];
$estado = $_POST['estado'];
$fecha = $_POST['fecha_presentacion'];
$sql = "UPDATE proyectos SET
titulo = '$titulo',
autor = '$autor',
tutor = '$tutor',
estado = '$estado',
fecha_presentacion = '$fecha'
WHERE id = $id";
echo json_encode(['success' => mysqli_query($con, $sql)]);
?>
9. delete_project.php
<?php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
include '[Link]';
$id = $_POST['id'];
$sql = "DELETE FROM proyectos WHERE id = $id";
echo json_encode(['success' => mysqli_query($con, $sql)]);
?>
10. 3. Estructura de la base de datos (MySQL)
CREATE TABLE proyectos (
id INT AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(255),
autor VARCHAR(255),
tutor VARCHAR(255),
estado VARCHAR(50),
fecha_presentacion DATE
);
11. 4. Código fuente de la aplicación móvil (Flutter)
Asegúrate de tener Flutter configurado y funcionando en tu máquina, así como tener acceso al servidor
local (XAMPP, Laragon o similar).
12. [Link]
import 'package:flutter/[Link]';
import 'package:http/[Link]' as http;
import 'dart:convert';
void main() {
runApp(MaterialApp(home: ProyectosGrado()));
class Proyecto {
int id;
String titulo;
String autor;
String tutor;
String estado;
String fechaPresentacion;
Proyecto({
required [Link],
required [Link],
required [Link],
required [Link],
required [Link],
required [Link],
});
factory [Link](Map<String, dynamic> json) => Proyecto(
id: [Link](json['id']),
titulo: json['titulo'],
autor: json['autor'],
tutor: json['tutor'],
estado: json['estado'],
fechaPresentacion: json['fecha_presentacion'],
);
class ProyectosGrado extends StatefulWidget {
@override
_ProyectosGradoState createState() => _ProyectosGradoState();
class _ProyectosGradoState extends State<ProyectosGrado> {
final String baseUrl = '[Link]
List<Proyecto> proyectos = [];
bool cargando = false;
final tituloCtrl = TextEditingController();
final autorCtrl = TextEditingController();
final tutorCtrl = TextEditingController();
final estadoCtrl = TextEditingController();
final fechaCtrl = TextEditingController();
int? idSeleccionado;
@override
void initState() {
[Link]();
obtenerProyectos();
Future<void> obtenerProyectos() async {
setState(() => cargando = true);
try {
final res = await [Link]([Link]('$baseUrl/get_projects.php'));
if ([Link] == 200) {
final List jsonData = [Link]([Link]);
setState(() {
proyectos = [Link]((p) => [Link](p)).toList();
});
} catch (e) {
print('Error: $e');
} finally {
setState(() => cargando = false);
Future<void> guardarProyecto() async {
if ([Link] || [Link]) return;
final body = {
'titulo': [Link],
'autor': [Link],
'tutor': [Link],
'estado': [Link],
'fecha_presentacion': [Link],
};
if (idSeleccionado != null) {
body['id'] = [Link]();
final url = idSeleccionado == null
? '$baseUrl/create_project.php'
: '$baseUrl/update_project.php';
final res = await [Link]([Link](url), body: body);
if ([Link] == 200) {
[Link](context).showSnackBar(
SnackBar(content: Text('Guardado correctamente')),
);
limpiarCampos();
obtenerProyectos();
Future<void> eliminarProyecto(int id) async {
final confirmado = await showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text('Eliminar'),
content: Text('¿Deseas eliminar este proyecto?'),
actions: [
TextButton(onPressed: () => [Link](context, false), child: Text('Cancelar')),
TextButton(onPressed: () => [Link](context, true), child: Text('Eliminar')),
],
),
);
if (confirmado) {
await [Link]([Link]('$baseUrl/delete_project.php'), body: {'id': '$id'});
[Link](context).showSnackBar(
SnackBar(content: Text('Eliminado exitosamente')),
);
obtenerProyectos();
void cargarDatos(Proyecto p) {
setState(() {
idSeleccionado = [Link];
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
});
void limpiarCampos() {
setState(() {
idSeleccionado = null;
[Link]();
[Link]();
[Link]();
[Link]();
[Link]();
});
Color colorEstado(String estado) {
switch ([Link]()) {
case 'activo':
return [Link];
case 'en proceso':
return [Link];
case 'terminado':
return [Link];
default:
return [Link];
}
Widget buildTabla() {
return SingleChildScrollView(
scrollDirection: [Link],
child: DataTable(
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Título')),
DataColumn(label: Text('Autor')),
DataColumn(label: Text('Estado')),
DataColumn(label: Text('Fecha')),
DataColumn(label: Text('Acciones')),
],
rows: [Link]((p) {
return DataRow(cells: [
DataCell(Text([Link]())),
DataCell(Text([Link])),
DataCell(Text([Link])),
DataCell(Text([Link], style: TextStyle(color: colorEstado([Link])))),
DataCell(Text([Link])),
DataCell(Row(
children: [
IconButton(icon: Icon([Link]), onPressed: () => cargarDatos(p)),
IconButton(icon: Icon([Link]), onPressed: () => eliminarProyecto([Link])),
],
)),
]);
}).toList(),
),
);
Widget buildForm() {
return Column(
children: [
TextField(controller: tituloCtrl, decoration: InputDecoration(labelText: 'Título')),
TextField(controller: autorCtrl, decoration: InputDecoration(labelText: 'Autor')),
TextField(controller: tutorCtrl, decoration: InputDecoration(labelText: 'Tutor')),
TextField(controller: estadoCtrl, decoration: InputDecoration(labelText: 'Estado')),
TextField(controller: fechaCtrl, decoration: InputDecoration(labelText: 'Fecha (YYYY-MM-DD)')),
SizedBox(height: 10),
ElevatedButton(
onPressed: guardarProyecto,
child: Text(idSeleccionado == null ? 'Guardar' : 'Actualizar'),
),
],
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Proyectos de Grado')),
body: Padding(
padding: const [Link](16),
child: Column(
children: [
buildForm(),
SizedBox(height: 20),
Expanded(child: cargando ? Center(child: CircularProgressIndicator()) : buildTabla()),
],
),
),
);